pg_test.go (7349B)
1 package postgres 2 3 import ( 4 "bytes" 5 "context" 6 "testing" 7 8 "github.com/jackc/pgx/v5/pgconn" 9 "github.com/jackc/pgx/v5/pgtype" 10 pgxmock "github.com/pashagolub/pgxmock/v4" 11 12 "git.defalsify.org/vise.git/db" 13 "git.defalsify.org/vise.git/db/dbtest" 14 ) 15 16 var ( 17 typMap = pgtype.NewMap() 18 19 mockVfd = pgconn.FieldDescription{ 20 Name: "value", 21 DataTypeOID: pgtype.ByteaOID, 22 Format: typMap.FormatCodeForOID(pgtype.ByteaOID), 23 } 24 ) 25 26 func TestCasesPg(t *testing.T) { 27 ctx := context.Background() 28 29 t.Skip("implement expects in all cases") 30 31 mock, err := pgxmock.NewPool() 32 if err != nil { 33 t.Fatal(err) 34 } 35 defer mock.Close() 36 37 store := NewPgDb().WithConnection(mock).WithSchema("vvise") 38 39 err = dbtest.RunTests(t, ctx, store) 40 if err != nil { 41 t.Fatal(err) 42 } 43 } 44 45 func TestPutGetPg(t *testing.T) { 46 var dbi db.Db 47 ses := "xyzzy" 48 49 mock, err := pgxmock.NewPool() 50 if err != nil { 51 t.Fatal(err) 52 } 53 defer mock.Close() 54 55 store := NewPgDb().WithConnection(mock).WithSchema("vvise") 56 store.SetPrefix(db.DATATYPE_USERDATA) 57 store.SetSession(ses) 58 ctx := context.Background() 59 60 dbi = store 61 _ = dbi 62 63 k := []byte("foo") 64 ks := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 65 ks = append(ks, []byte(".")...) 66 ks = append(ks, k...) 67 v := []byte("bar") 68 resInsert := pgxmock.NewResult("UPDATE", 1) 69 mock.ExpectBegin() 70 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 71 mock.ExpectCommit() 72 err = store.Put(ctx, k, v) 73 if err != nil { 74 t.Fatal(err) 75 } 76 77 row := pgxmock.NewRowsWithColumnDefinition(mockVfd) 78 row = row.AddRow(v) 79 mock.ExpectBegin() 80 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(ks).WillReturnRows(row) 81 mock.ExpectCommit() 82 b, err := store.Get(ctx, k) 83 if err != nil { 84 t.Fatal(err) 85 } 86 87 // TODO: implement as pgtype map instead, and btw also ask why getting base64 here 88 if !bytes.Equal(b, v) { 89 t.Fatalf("expected 'bar', got %x", b) 90 } 91 92 v = []byte("plugh") 93 mock.ExpectBegin() 94 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 95 mock.ExpectCommit() 96 err = store.Put(ctx, k, v) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 mock.ExpectBegin() 102 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 103 mock.ExpectCommit() 104 err = store.Put(ctx, k, v) 105 if err != nil { 106 t.Fatal(err) 107 } 108 109 row = pgxmock.NewRowsWithColumnDefinition(mockVfd) 110 row = row.AddRow(v) 111 mock.ExpectBegin() 112 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(ks).WillReturnRows(row) 113 mock.ExpectCommit() 114 b, err = store.Get(ctx, k) 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 if !bytes.Equal(b, v) { 120 t.Fatalf("expected 'plugh', got %x", b) 121 } 122 123 } 124 125 func TestPostgresTxAbort(t *testing.T) { 126 var dbi db.Db 127 ses := "xyzzy" 128 129 mock, err := pgxmock.NewPool() 130 if err != nil { 131 t.Fatal(err) 132 } 133 defer mock.Close() 134 135 store := NewPgDb().WithConnection(mock).WithSchema("vvise") 136 store.SetPrefix(db.DATATYPE_USERDATA) 137 store.SetSession(ses) 138 ctx := context.Background() 139 140 dbi = store 141 _ = dbi 142 143 resInsert := pgxmock.NewResult("UPDATE", 1) 144 k := []byte("foo") 145 ks := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 146 ks = append(ks, []byte(".")...) 147 ks = append(ks, k...) 148 v := []byte("bar") 149 //mock.ExpectBegin() 150 mock.ExpectBeginTx(defaultTxOptions) 151 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 152 mock.ExpectRollback() 153 err = store.Start(ctx) 154 if err != nil { 155 t.Fatal(err) 156 } 157 err = store.Put(ctx, k, v) 158 if err != nil { 159 t.Fatal(err) 160 } 161 store.Abort(ctx) 162 } 163 164 func TestPostgresTxCommitOnClose(t *testing.T) { 165 var dbi db.Db 166 ses := "xyzzy" 167 168 mock, err := pgxmock.NewPool() 169 if err != nil { 170 t.Fatal(err) 171 } 172 defer mock.Close() 173 174 store := NewPgDb().WithConnection(mock).WithSchema("vvise") 175 store.SetPrefix(db.DATATYPE_USERDATA) 176 store.SetSession(ses) 177 ctx := context.Background() 178 179 dbi = store 180 _ = dbi 181 182 resInsert := pgxmock.NewResult("UPDATE", 1) 183 k := []byte("foo") 184 ks := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 185 ks = append(ks, []byte(".")...) 186 ks = append(ks, k...) 187 v := []byte("bar") 188 189 ktwo := []byte("blinky") 190 kstwo := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 191 kstwo = append(kstwo, []byte(".")...) 192 kstwo = append(kstwo, ktwo...) 193 vtwo := []byte("clyde") 194 195 mock.ExpectBeginTx(defaultTxOptions) 196 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 197 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(kstwo, vtwo).WillReturnResult(resInsert) 198 mock.ExpectCommit() 199 200 err = store.Start(ctx) 201 if err != nil { 202 t.Fatal(err) 203 } 204 err = store.Put(ctx, k, v) 205 if err != nil { 206 t.Fatal(err) 207 } 208 err = store.Put(ctx, ktwo, vtwo) 209 if err != nil { 210 t.Fatal(err) 211 } 212 err = store.Close(ctx) 213 if err != nil { 214 t.Fatal(err) 215 } 216 217 row := pgxmock.NewRowsWithColumnDefinition(mockVfd) 218 row = row.AddRow(v) 219 mock.ExpectBeginTx(defaultTxOptions) 220 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(ks).WillReturnRows(row) 221 mock.ExpectCommit() 222 row = pgxmock.NewRowsWithColumnDefinition(mockVfd) 223 row = row.AddRow(vtwo) 224 mock.ExpectBeginTx(defaultTxOptions) 225 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(kstwo).WillReturnRows(row) 226 mock.ExpectCommit() 227 228 store = NewPgDb().WithConnection(mock).WithSchema("vvise") 229 store.SetPrefix(db.DATATYPE_USERDATA) 230 store.SetSession(ses) 231 v, err = store.Get(ctx, k) 232 if err != nil { 233 if !db.IsNotFound(err) { 234 t.Fatalf("get key one: %x", k) 235 } 236 } 237 v, err = store.Get(ctx, ktwo) 238 if err != nil { 239 if !db.IsNotFound(err) { 240 t.Fatalf("get key two: %x", ktwo) 241 } 242 } 243 } 244 245 func TestPostgresTxStartStop(t *testing.T) { 246 var dbi db.Db 247 ses := "xyzzy" 248 249 mock, err := pgxmock.NewPool() 250 if err != nil { 251 t.Fatal(err) 252 } 253 defer mock.Close() 254 255 store := NewPgDb().WithConnection(mock).WithSchema("vvise") 256 store.SetPrefix(db.DATATYPE_USERDATA) 257 store.SetSession(ses) 258 ctx := context.Background() 259 260 dbi = store 261 _ = dbi 262 263 resInsert := pgxmock.NewResult("UPDATE", 1) 264 k := []byte("inky") 265 ks := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 266 ks = append(ks, []byte(".")...) 267 ks = append(ks, k...) 268 v := []byte("pinky") 269 270 ktwo := []byte("blinky") 271 kstwo := append([]byte{db.DATATYPE_USERDATA}, []byte(ses)...) 272 kstwo = append(kstwo, []byte(".")...) 273 kstwo = append(kstwo, ktwo...) 274 vtwo := []byte("clyde") 275 mock.ExpectBeginTx(defaultTxOptions) 276 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(ks, v).WillReturnResult(resInsert) 277 mock.ExpectExec("INSERT INTO vvise.kv_vise").WithArgs(kstwo, vtwo).WillReturnResult(resInsert) 278 mock.ExpectCommit() 279 280 row := pgxmock.NewRowsWithColumnDefinition(mockVfd) 281 row = row.AddRow(v) 282 mock.ExpectBeginTx(defaultTxOptions) 283 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(ks).WillReturnRows(row) 284 row = pgxmock.NewRowsWithColumnDefinition(mockVfd) 285 row = row.AddRow(vtwo) 286 mock.ExpectQuery("SELECT value FROM vvise.kv_vise").WithArgs(kstwo).WillReturnRows(row) 287 mock.ExpectCommit() 288 289 err = store.Start(ctx) 290 if err != nil { 291 t.Fatal(err) 292 } 293 err = store.Put(ctx, k, v) 294 if err != nil { 295 t.Fatal(err) 296 } 297 err = store.Put(ctx, ktwo, vtwo) 298 if err != nil { 299 t.Fatal(err) 300 } 301 err = store.Stop(ctx) 302 if err != nil { 303 t.Fatal(err) 304 } 305 306 v, err = store.Get(ctx, k) 307 if err != nil { 308 t.Fatal(err) 309 } 310 v, err = store.Get(ctx, ktwo) 311 if err != nil { 312 t.Fatal(err) 313 } 314 err = store.Close(ctx) 315 if err != nil { 316 t.Fatal(err) 317 } 318 }