github.com/cloudfoundry/postgres-release/src/acceptance-tests@v0.0.0-20240511030151-872bdd2e0dba/testing/helpers/postgres_test.go (about) 1 package helpers_test 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "strings" 9 10 sqlmock "github.com/DATA-DOG/go-sqlmock" 11 "github.com/cloudfoundry/postgres-release/src/acceptance-tests/testing/helpers" 12 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 ) 16 17 var expectedcolumns = []string{"row_to_json"} 18 var genericError = fmt.Errorf("some error") 19 20 func convertQuery(query string) string { 21 //return helpers.GetFormattedQuery(query) 22 result := strings.Replace(helpers.GetFormattedQuery(query), ")", "\\)", -1) 23 result = strings.Replace(result, "(", "\\(", -1) 24 result = strings.Replace(result, ":", "\\:", -1) 25 result = strings.Replace(result, "+", "\\+", -1) 26 result = strings.Replace(result, "'", "\\'", -1) 27 return strings.Replace(result, "*", "(.+)", -1) 28 } 29 30 func mockSettings(expected map[string]string, mocks map[string]sqlmock.Sqlmock) { 31 if expected == nil { 32 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(helpers.GetSettingsQuery)).WillReturnError(genericError) 33 } else { 34 rows := sqlmock.NewRows(expectedcolumns) 35 for key, value := range expected { 36 ff := "{\"name\": \"%s\", \"setting\": \"%s\", \"some1\": \"%s\",\"vartype\": \"%s\"}" 37 row := fmt.Sprintf(ff, key, value, "some0", "string") 38 rows = rows.AddRow(row) 39 } 40 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(helpers.GetSettingsQuery)).WillReturnRows(rows) 41 } 42 } 43 44 func mockDatabases(expected []helpers.PGDatabase, mocks map[string]sqlmock.Sqlmock) { 45 if expected == nil { 46 mocks["dbsuper"].ExpectQuery(convertQuery(helpers.ListDatabasesQuery)).WillReturnError(genericError) 47 } else { 48 rows := sqlmock.NewRows(expectedcolumns) 49 for _, elem := range expected { 50 ff := "{\"datname\": \"%s\"}" 51 row := fmt.Sprintf(ff, elem.Name) 52 rows = rows.AddRow(row) 53 extrows := sqlmock.NewRows(expectedcolumns) 54 for _, elem := range elem.DBExts { 55 xx := "{\"extname\": \"%s\"}" 56 extrow := fmt.Sprintf(xx, elem.Name) 57 extrows = extrows.AddRow(extrow) 58 } 59 mocks[elem.Name+"super"].ExpectQuery(convertQuery(helpers.ListDBExtensionsQuery)).WillReturnRows(extrows) 60 tableRows := sqlmock.NewRows(expectedcolumns) 61 for _, tElem := range elem.Tables { 62 xx := "{\"schemaname\": \"%s\", \"tablename\":\"%s\",\"tableowner\":\"%s\"}" 63 tableRow := fmt.Sprintf(xx, tElem.SchemaName, tElem.TableName, tElem.TableOwner) 64 tableRows = tableRows.AddRow(tableRow) 65 } 66 mocks[elem.Name+"super"].ExpectQuery(convertQuery(helpers.ListTablesQuery)).WillReturnRows(tableRows) 67 for _, tElem := range elem.Tables { 68 columnRows := sqlmock.NewRows(expectedcolumns) 69 for _, col := range tElem.TableColumns { 70 xx := "{\"column_name\": \"%s\", \"data_type\":\"%s\",\"ordinal_position\":%d}" 71 columnRow := fmt.Sprintf(xx, col.ColumnName, col.DataType, col.Position) 72 columnRows = columnRows.AddRow(columnRow) 73 } 74 mocks[elem.Name+"super"].ExpectQuery(convertQuery(fmt.Sprintf(helpers.ListTableColumnsQuery, tElem.SchemaName, tElem.TableName))).WillReturnRows(columnRows) 75 countRows := sqlmock.NewRows(expectedcolumns) 76 countRows = countRows.AddRow(fmt.Sprintf("{\"count\": %d}", tElem.TableRowsCount.Num)) 77 mocks[elem.Name+"super"].ExpectQuery(convertQuery(fmt.Sprintf(helpers.CountTableRowsQuery, tElem.TableName))).WillReturnRows(countRows) 78 } 79 } 80 mocks["dbsuper"].ExpectQuery(convertQuery(helpers.ListDatabasesQuery)).WillReturnRows(rows) 81 } 82 } 83 func mockRoles(expected map[string]helpers.PGRole, mocks map[string]sqlmock.Sqlmock) error { 84 if expected == nil { 85 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(helpers.ListRolesQuery)).WillReturnError(genericError) 86 } else { 87 rows := sqlmock.NewRows(expectedcolumns) 88 for _, elem := range expected { 89 row, err := json.Marshal(elem) 90 if err != nil { 91 return err 92 } 93 rows = rows.AddRow(row) 94 } 95 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(helpers.ListRolesQuery)).WillReturnRows(rows) 96 } 97 return nil 98 } 99 func mockGetTable(expected map[string]helpers.PGTable, mocks map[string]sqlmock.Sqlmock, table_name string) error { 100 if expected == nil { 101 mocks["dbsuper"].ExpectQuery(convertQuery(fmt.Sprintf(helpers.GetTableQuery, table_name))).WillReturnError(genericError) 102 } else { 103 rows := sqlmock.NewRows(expectedcolumns) 104 for _, elem := range expected { 105 row, err := json.Marshal(elem) 106 if err != nil { 107 return err 108 } 109 rows = rows.AddRow(row) 110 } 111 mocks["dbsuper"].ExpectQuery(convertQuery(fmt.Sprintf(helpers.GetTableQuery, table_name))).WillReturnRows(rows) 112 fmt.Println(convertQuery(fmt.Sprintf(helpers.GetTableQuery, table_name))) 113 } 114 return nil 115 } 116 func mockGetRole(expected map[string]helpers.PGRole, mocks map[string]sqlmock.Sqlmock, role_name string) error { 117 if expected == nil { 118 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(fmt.Sprintf(helpers.GetRoleQuery, role_name))).WillReturnError(genericError) 119 } else { 120 rows := sqlmock.NewRows(expectedcolumns) 121 for _, elem := range expected { 122 row, err := json.Marshal(elem) 123 if err != nil { 124 return err 125 } 126 rows = rows.AddRow(row) 127 } 128 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(fmt.Sprintf(helpers.GetRoleQuery, role_name))).WillReturnRows(rows) 129 } 130 return nil 131 } 132 func mockDate(current string, expected string, mocks map[string]sqlmock.Sqlmock) error { 133 sqlCommand := convertQuery(fmt.Sprintf(helpers.ConvertToDateCommand, current)) 134 if expected == "" { 135 mocks[helpers.DefaultDB].ExpectQuery(sqlCommand).WillReturnError(genericError) 136 } else { 137 row := fmt.Sprintf("{\"timestamptz\": \"%s\"}", expected) 138 rows := sqlmock.NewRows(expectedcolumns).AddRow(row) 139 mocks[helpers.DefaultDB].ExpectQuery(sqlCommand).WillReturnRows(rows) 140 } 141 return nil 142 } 143 func mockPostgreSQLVersion(expected helpers.PGVersion, mocks map[string]sqlmock.Sqlmock) error { 144 sqlCommand := convertQuery(helpers.GetPostgreSQLVersionQuery) 145 if expected.Version == "" { 146 mocks[helpers.DefaultDB].ExpectQuery(sqlCommand).WillReturnError(genericError) 147 } else { 148 row := fmt.Sprintf("{\"version\": \"%s\"}", expected.Version) 149 rows := sqlmock.NewRows(expectedcolumns).AddRow(row) 150 mocks[helpers.DefaultDB].ExpectQuery(sqlCommand).WillReturnRows(rows) 151 } 152 return nil 153 } 154 155 var _ = Describe("Postgres", func() { 156 Describe("Copy output data", func() { 157 Context("Validate that data is copied", func() { 158 var from helpers.PGOutputData 159 160 BeforeEach(func() { 161 162 from = helpers.PGOutputData{ 163 Roles: map[string]helpers.PGRole{ 164 "role1": helpers.PGRole{ 165 Name: "role1", 166 }, 167 }, 168 Databases: []helpers.PGDatabase{ 169 helpers.PGDatabase{ 170 Name: "db1", 171 DBExts: []helpers.PGDatabaseExtensions{ 172 helpers.PGDatabaseExtensions{ 173 Name: "exta", 174 }, 175 }, 176 Tables: []helpers.PGTable{ 177 helpers.PGTable{ 178 SchemaName: "myschema1", 179 TableName: "mytable1", 180 TableOwner: "myowner1", 181 TableColumns: []helpers.PGTableColumn{ 182 helpers.PGTableColumn{ 183 ColumnName: "column1", 184 DataType: "type1", 185 Position: 1, 186 }, 187 }, 188 TableRowsCount: helpers.PGCount{Num: 90}, 189 }, 190 }, 191 }, 192 }, 193 Settings: map[string]string{ 194 "max_connections": "30", 195 }, 196 } 197 }) 198 It("Correctly copies roles", func() { 199 to, err := from.CopyData() 200 Expect(err).NotTo(HaveOccurred()) 201 Expect(to).To(Equal(from)) 202 r := to.Roles["role1"] 203 r.Name = "role2" 204 to.Roles["role1"] = r 205 Expect(to).NotTo(Equal(from)) 206 }) 207 It("Correctly copies settings", func() { 208 to, err := from.CopyData() 209 Expect(err).NotTo(HaveOccurred()) 210 Expect(to).To(Equal(from)) 211 to.Settings["max_connections"] = "xxx" 212 Expect(to).NotTo(Equal(from)) 213 }) 214 It("Correctly copies tables", func() { 215 to, err := from.CopyData() 216 Expect(err).NotTo(HaveOccurred()) 217 Expect(to).To(Equal(from)) 218 to.Databases[0].Tables[0].SchemaName = "xxxx" 219 Expect(to).NotTo(Equal(from)) 220 }) 221 It("Correctly copies columns", func() { 222 to, err := from.CopyData() 223 Expect(err).NotTo(HaveOccurred()) 224 Expect(to).To(Equal(from)) 225 to.Databases[0].Tables[0].TableColumns[0].ColumnName = "xxxx" 226 Expect(to).NotTo(Equal(from)) 227 }) 228 }) 229 }) 230 Describe("Validate common data", func() { 231 Context("Fail if common data is invalid", func() { 232 It("Fail if no address provided", func() { 233 props := helpers.PGCommon{ 234 Port: 10, 235 DefUser: helpers.User{ 236 Name: "uu", 237 Password: "pp", 238 }, 239 } 240 _, err := helpers.NewPostgres(props) 241 Expect(err).To(MatchError(errors.New(helpers.MissingDBAddressErr))) 242 }) 243 It("Fail if no port provided", func() { 244 props := helpers.PGCommon{ 245 Address: "bb.example.com", 246 DefUser: helpers.User{ 247 Name: "uu", 248 Password: "pp", 249 }, 250 } 251 _, err := helpers.NewPostgres(props) 252 Expect(err).To(MatchError(errors.New(helpers.MissingDBPortErr))) 253 }) 254 It("Fail if no default user provided", func() { 255 props := helpers.PGCommon{ 256 Address: "bb.example.com", 257 Port: 10, 258 DefUser: helpers.User{ 259 Password: "pp", 260 }, 261 } 262 _, err := helpers.NewPostgres(props) 263 Expect(err).To(MatchError(errors.New(helpers.MissingDefaultUserErr))) 264 }) 265 It("Fail if no default password provided", func() { 266 props := helpers.PGCommon{ 267 Address: "bb.example.com", 268 Port: 10, 269 DefUser: helpers.User{ 270 Name: "uu", 271 }, 272 } 273 _, err := helpers.NewPostgres(props) 274 Expect(err).To(MatchError(errors.New(helpers.MissingDefaultPasswordErr))) 275 }) 276 It("Fail if incorrect data provided", func() { 277 props := helpers.PGCommon{ 278 Address: "bb.example.com", 279 Port: 10, 280 DefUser: helpers.User{ 281 Name: "uu", 282 Password: "pp", 283 }, 284 } 285 pg, err := helpers.NewPostgres(props) 286 Expect(err).NotTo(HaveOccurred()) 287 _, err = pg.GetDefaultConnection() 288 Expect(err).To(MatchError(ContainSubstring("no such host"))) 289 }) 290 It("Fail if getting super user connection and no super user provided", func() { 291 props := helpers.PGCommon{ 292 Address: "bb.example.com", 293 Port: 10, 294 DefUser: helpers.User{ 295 Name: "uu", 296 Password: "pp", 297 }, 298 } 299 pg, err := helpers.NewPostgres(props) 300 Expect(err).NotTo(HaveOccurred()) 301 _, err = pg.GetSuperUserConnection() 302 Expect(err).To(MatchError(helpers.NoSuperUserProvidedErr)) 303 }) 304 It("Fail if incorrect sslmode provided", func() { 305 props := helpers.PGCommon{ 306 Address: "xx", 307 SSLMode: "unknown", 308 Port: 10, 309 DefUser: helpers.User{ 310 Name: "uu", 311 Password: "pp", 312 }, 313 } 314 _, err := helpers.NewPostgres(props) 315 Expect(err).To(MatchError(errors.New(helpers.IncorrectSSLModeErr))) 316 }) 317 }) 318 }) 319 Describe("Validate SSL mode", func() { 320 var ( 321 mocks map[string]sqlmock.Sqlmock 322 pg *helpers.PGData 323 ) 324 BeforeEach(func() { 325 mocks = make(map[string]sqlmock.Sqlmock) 326 db, mock, err := sqlmock.New() 327 Expect(err).NotTo(HaveOccurred()) 328 mocks[helpers.DefaultDB] = mock 329 pg = &helpers.PGData{ 330 Data: helpers.PGCommon{ 331 SSLMode: "disable", 332 }, 333 DBs: []helpers.PGConn{ 334 helpers.PGConn{ 335 DB: db, 336 TargetDB: helpers.DefaultDB, 337 }, 338 }, 339 } 340 }) 341 AfterEach(func() { 342 pg.CloseConnections() 343 }) 344 Context("Changing SSL mode", func() { 345 It("Fails to change to an invalid ssl mode", func() { 346 err := pg.ChangeSSLMode("unknown", "") 347 Expect(err).To(MatchError(errors.New(helpers.IncorrectSSLModeErr))) 348 }) 349 It("Correctly change to a valid ssl mode", func() { 350 err := pg.ChangeSSLMode("require", "") 351 Expect(err).NotTo(HaveOccurred()) 352 Expect(pg.Data.SSLMode).To(Equal("require")) 353 }) 354 It("Fails to change to stronger SSL modes if missing root cert", func() { 355 err := pg.ChangeSSLMode("verify-ca", "") 356 Expect(err).To(MatchError(errors.New(helpers.MissingSSLRootCertErr))) 357 }) 358 It("Correctly change to SSL modes that require root cert", func() { 359 err := pg.ChangeSSLMode("verify-ca", "/somepath") 360 Expect(err).NotTo(HaveOccurred()) 361 Expect(pg.Data.SSLMode).To(Equal("verify-ca")) 362 }) 363 It("Correctly close connections when changing ssl mode", func() { 364 _, err := pg.GetDefaultConnection() 365 Expect(err).NotTo(HaveOccurred()) 366 Expect(pg.DBs).NotTo(BeNil()) 367 err = pg.ChangeSSLMode("verify-full", "/some-path") 368 Expect(err).NotTo(HaveOccurred()) 369 Expect(pg.Data.SSLMode).To(Equal("verify-full")) 370 conns := 0 371 if pg.DBs != nil { 372 conns = len(pg.DBs) 373 } 374 Expect(conns).To(BeZero()) 375 }) 376 }) 377 }) 378 Describe("Run read-only queries", func() { 379 var ( 380 mocks map[string]sqlmock.Sqlmock 381 pg *helpers.PGData 382 ) 383 384 BeforeEach(func() { 385 mocks = make(map[string]sqlmock.Sqlmock) 386 db, mock, err := sqlmock.New() 387 Expect(err).NotTo(HaveOccurred()) 388 mocks[helpers.DefaultDB] = mock 389 db1, mock1, err := sqlmock.New() 390 Expect(err).NotTo(HaveOccurred()) 391 mocks["db1"] = mock1 392 db2, mock2, err := sqlmock.New() 393 Expect(err).NotTo(HaveOccurred()) 394 mocks["db2"] = mock2 395 dbsuper, mocksuper, err := sqlmock.New() 396 Expect(err).NotTo(HaveOccurred()) 397 mocks["dbsuper"] = mocksuper 398 db1super, mock1super, err := sqlmock.New() 399 Expect(err).NotTo(HaveOccurred()) 400 mocks["db1super"] = mock1super 401 db2super, mock2super, err := sqlmock.New() 402 Expect(err).NotTo(HaveOccurred()) 403 mocks["db2super"] = mock2super 404 pg = &helpers.PGData{ 405 Data: helpers.PGCommon{ 406 DefUser: helpers.User{ 407 Name: "defUser", 408 Password: "defPassword", 409 }, 410 AdminUser: helpers.User{ 411 Name: "superUser", 412 Password: "superPassword", 413 }, 414 }, 415 DBs: []helpers.PGConn{ 416 helpers.PGConn{ 417 DB: db, 418 User: "defUser", 419 TargetDB: helpers.DefaultDB, 420 }, 421 helpers.PGConn{ 422 DB: db1, 423 User: "defUser", 424 TargetDB: "db1", 425 }, 426 helpers.PGConn{ 427 DB: db2, 428 User: "defUser", 429 TargetDB: "db2", 430 }, 431 helpers.PGConn{ 432 DB: dbsuper, 433 User: "superUser", 434 TargetDB: helpers.DefaultDB, 435 }, 436 helpers.PGConn{ 437 DB: db1super, 438 User: "superUser", 439 TargetDB: "db1", 440 }, 441 helpers.PGConn{ 442 DB: db2super, 443 User: "superUser", 444 TargetDB: "db2", 445 }, 446 }, 447 } 448 }) 449 AfterEach(func() { 450 pg.CloseConnections() 451 }) 452 Context("Run a generic query", func() { 453 It("Returns all the lines", func() { 454 expected := []string{ 455 "{\"name\": \"pgadmin1\", \"role\": \"admin\"}", 456 "{\"name\": \"pgadmin2\", \"role\": \"admin\"}", 457 } 458 rows := sqlmock.NewRows(expectedcolumns). 459 AddRow(expected[0]). 460 AddRow(expected[1]) 461 query := "SELECT name,role FROM table" 462 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(query)).WillReturnRows(rows) 463 conn, err := pg.GetDefaultConnection() 464 Expect(err).NotTo(HaveOccurred()) 465 result, err := conn.Run(query) 466 Expect(err).NotTo(HaveOccurred()) 467 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 468 Expect(err).NotTo(HaveOccurred()) 469 } 470 Expect(result).To(Equal(expected)) 471 }) 472 It("Properly reports a failure", func() { 473 query := "SELECT name,role FROM table" 474 mocks[helpers.DefaultDB].ExpectQuery(convertQuery(query)).WillReturnError(genericError) 475 conn, err := pg.GetDefaultConnection() 476 Expect(err).NotTo(HaveOccurred()) 477 _, err = conn.Run(query) 478 Expect(err).To(MatchError(genericError)) 479 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 480 Expect(err).NotTo(HaveOccurred()) 481 } 482 }) 483 }) 484 Context("Fail to retrieve env info", func() { 485 It("Fails to read postgresql version", func() { 486 mockPostgreSQLVersion(helpers.PGVersion{Version: ""}, mocks) 487 _, err := pg.GetPostgreSQLVersion() 488 Expect(err).To(MatchError(genericError)) 489 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 490 Expect(err).NotTo(HaveOccurred()) 491 } 492 }) 493 It("Fails to read pg_settings", func() { 494 mockSettings(nil, mocks) 495 _, err := pg.ReadAllSettings() 496 Expect(err).To(MatchError(genericError)) 497 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 498 Expect(err).NotTo(HaveOccurred()) 499 } 500 }) 501 It("Fails to list databases", func() { 502 mockDatabases(nil, mocks) 503 _, err := pg.ListDatabases() 504 Expect(err).To(MatchError(genericError)) 505 if err = mocks["dbsuper"].ExpectationsWereMet(); err != nil { 506 Expect(err).NotTo(HaveOccurred()) 507 } 508 }) 509 It("Fails to list roles", func() { 510 err := mockRoles(nil, mocks) 511 Expect(err).NotTo(HaveOccurred()) 512 _, err = pg.ListRoles() 513 Expect(err).To(MatchError(genericError)) 514 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 515 Expect(err).NotTo(HaveOccurred()) 516 } 517 }) 518 It("Fails to convert date to postgres date", func() { 519 err := mockDate("xxx", "", mocks) 520 Expect(err).NotTo(HaveOccurred()) 521 _, err = pg.ConvertToPostgresDate("xxx") 522 Expect(err).To(MatchError(genericError)) 523 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 524 Expect(err).NotTo(HaveOccurred()) 525 } 526 }) 527 It("Fails to check that role exist", func() { 528 expected := map[string]helpers.PGRole{} 529 err := mockGetRole(expected, mocks, "role1") 530 Expect(err).NotTo(HaveOccurred()) 531 result, err := pg.CheckRoleExist("role1") 532 Expect(err).NotTo(HaveOccurred()) 533 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 534 Expect(err).NotTo(HaveOccurred()) 535 } 536 Expect(result).To(BeFalse()) 537 }) 538 It("Fails to check that table exist", func() { 539 expected := map[string]helpers.PGTable{} 540 err := mockGetTable(expected, mocks, "table1") 541 Expect(err).NotTo(HaveOccurred()) 542 result, err := pg.CheckTableExist("table1", helpers.DefaultDB) 543 Expect(err).NotTo(HaveOccurred()) 544 if err = mocks["dbsuper"].ExpectationsWereMet(); err != nil { 545 Expect(err).NotTo(HaveOccurred()) 546 } 547 Expect(result).To(BeFalse()) 548 }) 549 }) 550 Context("Correctly retrieve env info", func() { 551 It("Correctly get postgresql version", func() { 552 version := "PostgreSQL 9.4.9" 553 mockPostgreSQLVersion(helpers.PGVersion{Version: version}, mocks) 554 result, err := pg.GetPostgreSQLVersion() 555 Expect(err).NotTo(HaveOccurred()) 556 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 557 Expect(err).NotTo(HaveOccurred()) 558 } 559 Expect(result.Version).To(Equal(version)) 560 }) 561 It("Correctly read pg_settings", func() { 562 expected := map[string]string{ 563 "a1": "a2", 564 "b1": "b2", 565 } 566 mockSettings(expected, mocks) 567 result, err := pg.ReadAllSettings() 568 Expect(err).NotTo(HaveOccurred()) 569 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 570 Expect(err).NotTo(HaveOccurred()) 571 } 572 Expect(result).NotTo(BeZero()) 573 Expect(result).To(Equal(expected)) 574 }) 575 It("Correctly lists databases without extensions", func() { 576 expected := []helpers.PGDatabase{ 577 helpers.PGDatabase{ 578 Name: "db1", 579 DBExts: []helpers.PGDatabaseExtensions{}, 580 Tables: []helpers.PGTable{}, 581 }, 582 helpers.PGDatabase{ 583 Name: "db2", 584 DBExts: []helpers.PGDatabaseExtensions{}, 585 Tables: []helpers.PGTable{}, 586 }, 587 } 588 mockDatabases(expected, mocks) 589 result, err := pg.ListDatabases() 590 Expect(err).NotTo(HaveOccurred()) 591 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 592 Expect(err).NotTo(HaveOccurred()) 593 } 594 if err = mocks["db1"].ExpectationsWereMet(); err != nil { 595 Expect(err).NotTo(HaveOccurred()) 596 } 597 if err = mocks["db2"].ExpectationsWereMet(); err != nil { 598 Expect(err).NotTo(HaveOccurred()) 599 } 600 Expect(result).To(Equal(expected)) 601 }) 602 It("Correctly lists databases with extensions", func() { 603 expected := []helpers.PGDatabase{ 604 helpers.PGDatabase{ 605 Name: "db1", 606 DBExts: []helpers.PGDatabaseExtensions{ 607 helpers.PGDatabaseExtensions{ 608 Name: "exta", 609 }, 610 helpers.PGDatabaseExtensions{ 611 Name: "extb", 612 }, 613 }, 614 Tables: []helpers.PGTable{}, 615 }, 616 } 617 mockDatabases(expected, mocks) 618 result, err := pg.ListDatabases() 619 Expect(err).NotTo(HaveOccurred()) 620 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 621 Expect(err).NotTo(HaveOccurred()) 622 } 623 if err = mocks["db1"].ExpectationsWereMet(); err != nil { 624 Expect(err).NotTo(HaveOccurred()) 625 } 626 Expect(result).To(Equal(expected)) 627 }) 628 It("Correctly lists databases with tables", func() { 629 expected := []helpers.PGDatabase{ 630 helpers.PGDatabase{ 631 Name: "db1", 632 DBExts: []helpers.PGDatabaseExtensions{}, 633 Tables: []helpers.PGTable{ 634 helpers.PGTable{ 635 SchemaName: "myschema1", 636 TableName: "mytable1", 637 TableOwner: "myowner1", 638 TableColumns: []helpers.PGTableColumn{ 639 helpers.PGTableColumn{ 640 ColumnName: "column1", 641 DataType: "type1", 642 Position: 1, 643 }, 644 helpers.PGTableColumn{ 645 ColumnName: "column2", 646 DataType: "type2", 647 Position: 2, 648 }, 649 }, 650 TableRowsCount: helpers.PGCount{Num: 90}, 651 }, 652 helpers.PGTable{ 653 SchemaName: "myschema2", 654 TableName: "mytable2", 655 TableOwner: "myowner2", 656 TableColumns: []helpers.PGTableColumn{ 657 helpers.PGTableColumn{ 658 ColumnName: "column3", 659 DataType: "type3", 660 Position: 0, 661 }, 662 }, 663 TableRowsCount: helpers.PGCount{Num: 0}, 664 }, 665 }, 666 }, 667 } 668 mockDatabases(expected, mocks) 669 result, err := pg.ListDatabases() 670 Expect(err).NotTo(HaveOccurred()) 671 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 672 Expect(err).NotTo(HaveOccurred()) 673 } 674 if err = mocks["db1"].ExpectationsWereMet(); err != nil { 675 Expect(err).NotTo(HaveOccurred()) 676 } 677 Expect(result).To(Equal(expected)) 678 }) 679 It("Correctly lists roles with properties", func() { 680 expected := map[string]helpers.PGRole{ 681 "role1": helpers.PGRole{ 682 Name: "role1", 683 Super: true, 684 Inherit: false, 685 CreateRole: false, 686 CreateDb: true, 687 CanLogin: true, 688 Replication: false, 689 ConnLimit: 10, 690 ValidUntil: "", 691 }, 692 "role2": helpers.PGRole{ 693 Name: "role2", 694 Super: false, 695 Inherit: true, 696 CreateRole: true, 697 CreateDb: false, 698 CanLogin: false, 699 Replication: true, 700 ConnLimit: 100, 701 ValidUntil: "xxx", 702 }, 703 } 704 err := mockRoles(expected, mocks) 705 Expect(err).NotTo(HaveOccurred()) 706 result, err := pg.ListRoles() 707 Expect(err).NotTo(HaveOccurred()) 708 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 709 Expect(err).NotTo(HaveOccurred()) 710 } 711 Expect(result).To(Equal(expected)) 712 }) 713 It("Correctly checks that role exists", func() { 714 expected := map[string]helpers.PGRole{ 715 "role1": helpers.PGRole{ 716 Name: "role1", 717 }, 718 } 719 err := mockGetRole(expected, mocks, "role1") 720 Expect(err).NotTo(HaveOccurred()) 721 result, err := pg.CheckRoleExist("role1") 722 Expect(err).NotTo(HaveOccurred()) 723 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 724 Expect(err).NotTo(HaveOccurred()) 725 } 726 Expect(result).To(BeTrue()) 727 }) 728 It("Correctly checks that table exists", func() { 729 var table1 helpers.PGTable 730 table1.TableName = "table1" 731 expected := map[string]helpers.PGTable{ 732 "table1": table1, 733 } 734 err := mockGetTable(expected, mocks, "table1") 735 Expect(err).NotTo(HaveOccurred()) 736 result, err := pg.CheckTableExist("table1", helpers.DefaultDB) 737 Expect(err).NotTo(HaveOccurred()) 738 if err = mocks["dbsuper"].ExpectationsWereMet(); err != nil { 739 Expect(err).NotTo(HaveOccurred()) 740 } 741 Expect(result).To(BeTrue()) 742 }) 743 It("Correctly retrieves all postgres data", func() { 744 expected := helpers.PGOutputData{ 745 Roles: map[string]helpers.PGRole{ 746 "pgadmin": helpers.PGRole{ 747 Name: "pgadmin", 748 CanLogin: true, 749 ConnLimit: 20, 750 }, 751 }, 752 Databases: []helpers.PGDatabase{ 753 helpers.PGDatabase{ 754 Name: "db1", 755 DBExts: []helpers.PGDatabaseExtensions{}, 756 Tables: []helpers.PGTable{}, 757 }, 758 }, 759 Settings: map[string]string{ 760 "max_connections": "30", 761 }, 762 Version: helpers.PGVersion{ 763 Version: "PostgreSQL 9.4.9", 764 }, 765 } 766 mockSettings(expected.Settings, mocks) 767 mockDatabases(expected.Databases, mocks) 768 err := mockRoles(expected.Roles, mocks) 769 Expect(err).NotTo(HaveOccurred()) 770 mockPostgreSQLVersion(expected.Version, mocks) 771 result, err := pg.GetData() 772 Expect(err).NotTo(HaveOccurred()) 773 if err = mocks[helpers.DefaultDB].ExpectationsWereMet(); err != nil { 774 Expect(err).NotTo(HaveOccurred()) 775 } 776 if err = mocks["db1"].ExpectationsWereMet(); err != nil { 777 Expect(err).NotTo(HaveOccurred()) 778 } 779 Expect(result).NotTo(BeZero()) 780 Expect(result).To(Equal(expected)) 781 }) 782 It("Correctly converts date to postgres date", func() { 783 input := "May 5 12:00:00 2017 +1" 784 expected := "2017-05-05 11:00:00" 785 err := mockDate(input, expected, mocks) 786 Expect(err).NotTo(HaveOccurred()) 787 result, err := pg.ConvertToPostgresDate(input) 788 Expect(err).NotTo(HaveOccurred()) 789 Expect(result).To(Equal(expected)) 790 }) 791 It("Correctly converts date with quotes to postgres date", func() { 792 input := "May 5 12:00:00 2017 +1" 793 inputQuotes := fmt.Sprintf("'%s'", input) 794 expected := "2017-05-05 11:00:00" 795 err := mockDate(input, expected, mocks) 796 Expect(err).NotTo(HaveOccurred()) 797 result, err := pg.ConvertToPostgresDate(inputQuotes) 798 Expect(err).NotTo(HaveOccurred()) 799 Expect(result).To(Equal(expected)) 800 }) 801 }) 802 }) 803 Describe("Load DB", func() { 804 var ( 805 mock sqlmock.Sqlmock 806 pg *helpers.PGData 807 prepared string 808 ) 809 Context("Load DB with a table", func() { 810 811 BeforeEach(func() { 812 var db *sql.DB 813 var err error 814 db, mock, err = sqlmock.New() 815 Expect(err).NotTo(HaveOccurred()) 816 pg = &helpers.PGData{ 817 Data: helpers.PGCommon{}, 818 DBs: []helpers.PGConn{ 819 helpers.PGConn{DB: db, TargetDB: "db1"}, 820 }, 821 } 822 prepared = `COPY "pgats_table_0" ("column0") FROM STDIN` 823 prepared = strings.Replace(prepared, ")", "\\)", -1) 824 prepared = strings.Replace(prepared, "(", "\\(", -1) 825 }) 826 AfterEach(func() { 827 for _, conn := range pg.DBs { 828 conn.DB.Close() 829 } 830 }) 831 It("Correctly create and drop the table", func() { 832 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 833 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 834 mock.ExpectBegin() 835 mock.ExpectPrepare(prepared) 836 mock.ExpectExec(prepared).WithArgs("short_string0").WillReturnResult(sqlmock.NewResult(1, 1)) 837 mock.ExpectExec("").WillReturnResult(sqlmock.NewResult(1, 1)) 838 mock.ExpectCommit() 839 mock.ExpectExec("DROP TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 840 841 err := pg.CreateAndPopulateTablesWithPrefix("db1", helpers.Test1Load, "pgats_table") 842 Expect(err).NotTo(HaveOccurred()) 843 err = pg.DropTable("db1", "pgats_table_0") 844 Expect(err).NotTo(HaveOccurred()) 845 846 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 847 }) 848 It("Fails to create the table", func() { 849 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnError(genericError) 850 851 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 852 Expect(err).To(MatchError(genericError)) 853 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 854 }) 855 It("Fails to create the index", func() { 856 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 857 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnError(genericError) 858 859 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 860 Expect(err).To(MatchError(genericError)) 861 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 862 }) 863 It("Fails to begin the connection", func() { 864 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 865 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 866 mock.ExpectBegin().WillReturnError(genericError) 867 868 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 869 Expect(err).To(MatchError(genericError)) 870 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 871 }) 872 It("Fails to prepare the statement", func() { 873 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 874 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 875 mock.ExpectBegin() 876 mock.ExpectPrepare(prepared).WillReturnError(genericError) 877 878 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 879 Expect(err).To(MatchError(genericError)) 880 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 881 }) 882 It("Fails to populate row", func() { 883 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 884 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 885 mock.ExpectBegin() 886 mock.ExpectPrepare(prepared) 887 mock.ExpectExec(prepared).WithArgs("short_string0").WillReturnError(genericError) 888 889 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 890 Expect(err).To(MatchError(genericError)) 891 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 892 }) 893 It("Fails to flush buffered data", func() { 894 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 895 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 896 mock.ExpectBegin() 897 mock.ExpectPrepare(prepared) 898 mock.ExpectExec(prepared).WithArgs("short_string0").WillReturnResult(sqlmock.NewResult(1, 1)) 899 mock.ExpectExec("").WillReturnError(genericError) 900 901 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 902 Expect(err).To(MatchError(genericError)) 903 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 904 }) 905 It("Fails to commit", func() { 906 mock.ExpectExec("CREATE TABLE pgats_table_0").WillReturnResult(sqlmock.NewResult(1, 1)) 907 mock.ExpectExec("CREATE INDEX pgats_table_0_index ON pgats_table_0 USING hash").WillReturnResult(sqlmock.NewResult(1, 1)) 908 mock.ExpectBegin() 909 mock.ExpectPrepare(prepared) 910 mock.ExpectExec(prepared).WithArgs("short_string0").WillReturnResult(sqlmock.NewResult(1, 1)) 911 mock.ExpectExec("").WillReturnResult(sqlmock.NewResult(1, 1)) 912 mock.ExpectCommit().WillReturnError(genericError) 913 914 err := pg.CreateAndPopulateTables("db1", helpers.Test1Load) 915 Expect(err).To(MatchError(genericError)) 916 Expect(mock.ExpectationsWereMet()).NotTo(HaveOccurred()) 917 }) 918 }) 919 }) 920 })