github.com/tuhaihe/gpbackup@v1.0.3/restore/wrappers_test.go (about) 1 package restore_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 8 "github.com/DATA-DOG/go-sqlmock" 9 "github.com/tuhaihe/gp-common-go-libs/cluster" 10 "github.com/tuhaihe/gp-common-go-libs/testhelper" 11 "github.com/tuhaihe/gpbackup/history" 12 "github.com/tuhaihe/gpbackup/options" 13 "github.com/tuhaihe/gpbackup/restore" 14 "github.com/tuhaihe/gpbackup/testutils" 15 "github.com/tuhaihe/gpbackup/toc" 16 "github.com/tuhaihe/gpbackup/utils" 17 "github.com/pkg/errors" 18 19 . "github.com/onsi/ginkgo/v2" 20 . "github.com/onsi/gomega" 21 ) 22 23 var _ = Describe("wrapper tests", func() { 24 Describe("SetMaxCsvLineLengthQuery", func() { 25 It("returns nothing with a connection version of at least 6.0.0", func() { 26 testhelper.SetDBVersion(connectionPool, "6.0.0") 27 result := restore.SetMaxCsvLineLengthQuery(connectionPool) 28 Expect(result).To(Equal("")) 29 }) 30 It("sets gp_max_csv_line_length to 1GB when connection version is 4.X and at least 4.3.30.0", func() { 31 Skip("Test is not applicable to cloudberry 1.0+") 32 testhelper.SetDBVersion(connectionPool, "4.3.30") 33 result := restore.SetMaxCsvLineLengthQuery(connectionPool) 34 Expect(result).To(Equal("SET gp_max_csv_line_length = 1073741824;\n")) 35 }) 36 It("sets gp_max_csv_line_length to 1GB when connection version is 5.X and at least 5.11.0", func() { 37 Skip("Test is not applicable to cloudberry 1.0+") 38 testhelper.SetDBVersion(connectionPool, "5.11.0") 39 result := restore.SetMaxCsvLineLengthQuery(connectionPool) 40 Expect(result).To(Equal("SET gp_max_csv_line_length = 1073741824;\n")) 41 }) 42 It("sets gp_max_csv_line_length to 4MB when connection version is 4.X and before 4.3.30.0", func() { 43 Skip("Test is not applicable to cloudberry 1.0+") 44 testhelper.SetDBVersion(connectionPool, "4.3.29") 45 result := restore.SetMaxCsvLineLengthQuery(connectionPool) 46 Expect(result).To(Equal("SET gp_max_csv_line_length = 4194304;\n")) 47 }) 48 It("sets gp_max_csv_line_length to 4MB when connection version is 5.X and before 5.11.0", func() { 49 Skip("Test is not applicable to cloudberry 1.0+") 50 testhelper.SetDBVersion(connectionPool, "5.10.999") 51 result := restore.SetMaxCsvLineLengthQuery(connectionPool) 52 Expect(result).To(Equal("SET gp_max_csv_line_length = 4194304;\n")) 53 }) 54 }) 55 Describe("RestoreSchemas", func() { 56 var ( 57 ignoredProgressBar utils.ProgressBar 58 schemaArray = []toc.StatementWithType{{Name: "foo", Statement: "create schema foo"}} 59 ) 60 BeforeEach(func() { 61 ignoredProgressBar = utils.NewProgressBar(1, "", utils.PB_NONE) 62 ignoredProgressBar.Start() 63 }) 64 AfterEach(func() { 65 ignoredProgressBar.Finish() 66 }) 67 It("logs nothing if there are no errors", func() { 68 expectedResult := sqlmock.NewResult(0, 1) 69 mock.ExpectExec("create schema foo").WillReturnResult(expectedResult) 70 71 restore.RestoreSchemas(schemaArray, ignoredProgressBar) 72 73 testhelper.NotExpectRegexp(logfile, "Schema foo already exists") 74 testhelper.NotExpectRegexp(logfile, "Error encountered while creating schema foo") 75 }) 76 It("logs warning if schema already exists", func() { 77 expectedErr := errors.New(`schema "foo" already exists`) 78 mock.ExpectExec("create schema foo").WillReturnError(expectedErr) 79 80 restore.RestoreSchemas(schemaArray, ignoredProgressBar) 81 82 testhelper.ExpectRegexp(logfile, "[WARNING]:-Schema foo already exists") 83 }) 84 It("logs error if --on-error-continue is set", func() { 85 _ = cmdFlags.Set(options.ON_ERROR_CONTINUE, "true") 86 defer cmdFlags.Set(options.ON_ERROR_CONTINUE, "false") 87 expectedErr := errors.New("some other schema error") 88 mock.ExpectExec("create schema foo").WillReturnError(expectedErr) 89 90 restore.RestoreSchemas(schemaArray, ignoredProgressBar) 91 92 expectedDebugMsg := "[DEBUG]:-Error encountered while creating schema foo: some other schema error" 93 testhelper.ExpectRegexp(logfile, expectedDebugMsg) 94 expectedErrMsg := "[ERROR]:-Encountered 1 errors during schema restore; see log file gbytes.Buffer for a list of errors." 95 testhelper.ExpectRegexp(logfile, expectedErrMsg) 96 }) 97 It("panics if create schema statement fails", func() { 98 expectedErr := errors.New("some other schema error") 99 mock.ExpectExec("create schema foo").WillReturnError(expectedErr) 100 expectedPanicMsg := "[CRITICAL]:-some other schema error: Error encountered while creating schema foo" 101 defer testhelper.ShouldPanicWithMessage(expectedPanicMsg) 102 103 restore.RestoreSchemas(schemaArray, ignoredProgressBar) 104 }) 105 }) 106 Describe("SetRestorePlanForLegacyBackup", func() { 107 legacyBackupConfig := history.BackupConfig{} 108 legacyBackupConfig.RestorePlan = nil 109 legacyBackupTOC := toc.TOC{ 110 DataEntries: []toc.CoordinatorDataEntry{ 111 {Schema: "schema1", Name: "table1"}, 112 {Schema: "schema2", Name: "table2"}, 113 }, 114 } 115 legacyBackupTimestamp := "ts0" 116 117 restore.SetRestorePlanForLegacyBackup(&legacyBackupTOC, legacyBackupTimestamp, &legacyBackupConfig) 118 119 Specify("That there should be only one resultant restore plan entry", func() { 120 Expect(legacyBackupConfig.RestorePlan).To(HaveLen(1)) 121 }) 122 123 Specify("That the restore plan entry should have the legacy backup's timestamp", func() { 124 Expect(legacyBackupConfig.RestorePlan[0].Timestamp).To(Equal(legacyBackupTimestamp)) 125 }) 126 127 Specify("That the restore plan entry should have all table FQNs as in the TOC's DataEntries", func() { 128 Expect(legacyBackupConfig.RestorePlan[0].TableFQNs). 129 To(Equal([]string{"schema1.table1", "schema2.table2"})) 130 }) 131 132 }) 133 Describe("restore history tests", func() { 134 sampleConfigContents := ` 135 executablepath: /bin/echo 136 options: 137 hostname: "10.85.20.10" 138 storage_unit: "GPDB" 139 username: "gpadmin" 140 password: "changeme" 141 password_encryption: 142 directory: "/blah" 143 replication: "off" 144 remote_hostname: "10.85.20.11" 145 remote_storage_unit: "GPDB" 146 remote_username: "gpadmin" 147 remote_password: "changeme" 148 remote_directory: "/blah" 149 pgport: 1234 150 ` 151 152 sampleBackupHistory := ` 153 backupconfigs: 154 - backupdir: "" 155 backupversion: 1.11.0+dev.28.g10571fd 156 compressed: false 157 databasename: plugin_test_db 158 databaseversion: 4.3.99.0+dev.18.gb29642fb22 build dev 159 dataonly: false 160 deleted: false 161 excluderelations: [] 162 excludeschemafiltered: false 163 excludeschemas: [] 164 excludetablefiltered: false 165 includerelations: [] 166 includeschemafiltered: false 167 includeschemas: [] 168 includetablefiltered: false 169 incremental: false 170 leafpartitiondata: false 171 metadataonly: false 172 plugin: /Users/pivotal/workspace/gp-backup-ddboost-plugin/gpbackup_ddboost_plugin 173 restoreplan: 174 - timestamp: "20170415154408" 175 tablefqns: 176 - public.test_table 177 singledatafile: false 178 timestamp: "20170415154408" 179 withstatistics: false 180 - backupdir: "" 181 backupversion: 1.11.0+dev.28.g10571fd 182 compressed: false 183 databasename: plugin_test_db 184 databaseversion: 4.3.99.0+dev.18.gb29642fb22 build dev 185 dataonly: false 186 deleted: false 187 excluderelations: [] 188 excludeschemafiltered: false 189 excludeschemas: [] 190 excludetablefiltered: false 191 includerelations: [] 192 includeschemafiltered: false 193 includeschemas: [] 194 includetablefiltered: false 195 incremental: false 196 leafpartitiondata: false 197 metadataonly: false 198 plugin: /Users/pivotal/workspace/gp-backup-ddboost-plugin/gpbackup_ddboost_plugin 199 pluginversion: "99.99.9999" 200 restoreplan: 201 - timestamp: "20180415154238" 202 tablefqns: 203 - public.test_table 204 singledatafile: true 205 timestamp: "20180415154238" 206 withstatistics: false 207 ` 208 209 sampleBackupConfig := ` 210 backupdir: "" 211 backupversion: 1.11.0+dev.28.g10571fd 212 compressed: false 213 databasename: plugin_test_db 214 databaseversion: 4.3.99.0+dev.18.gb29642fb22 build dev 215 dataonly: false 216 deleted: false 217 excluderelations: [] 218 excludeschemafiltered: false 219 excludeschemas: [] 220 excludetablefiltered: false 221 includerelations: [] 222 includeschemafiltered: false 223 includeschemas: [] 224 includetablefiltered: false 225 incremental: false 226 leafpartitiondata: false 227 metadataonly: false 228 plugin: /Users/pivotal/workspace/gp-backup-ddboost-plugin/gpbackup_ddboost_plugin 229 pluginversion: "99.99.9999" 230 restoreplan: 231 - timestamp: "20180415154238" 232 tablefqns: 233 - public.test_table 234 singledatafile: true 235 timestamp: "20180415154238" 236 withstatistics: false 237 ` 238 var executor testutils.TestExecutorMultiple 239 var testConfigPath = "/tmp/unit_test_plugin_config.yml" 240 var oldWd string 241 var mdd string 242 var tempDir string 243 244 BeforeEach(func() { 245 tempDir, _ = ioutil.TempDir("", "temp") 246 247 err := ioutil.WriteFile(testConfigPath, []byte(sampleConfigContents), 0777) 248 Expect(err).ToNot(HaveOccurred()) 249 err = cmdFlags.Set(options.PLUGIN_CONFIG, testConfigPath) 250 Expect(err).ToNot(HaveOccurred()) 251 252 executor = testutils.TestExecutorMultiple{ 253 ClusterOutputs: make([]*cluster.RemoteOutput, 2), 254 } 255 executor.ClusterOutputs[0] = &cluster.RemoteOutput{ 256 Commands: []cluster.ShellCommand{ 257 cluster.ShellCommand{Stdout: utils.RequiredPluginVersion}, 258 cluster.ShellCommand{Stdout: utils.RequiredPluginVersion}, 259 cluster.ShellCommand{Stdout: utils.RequiredPluginVersion}, 260 }, 261 } 262 executor.ClusterOutputs[1] = &cluster.RemoteOutput{ 263 Commands: []cluster.ShellCommand{ 264 cluster.ShellCommand{Stdout: "myPlugin version 1.2.3"}, 265 cluster.ShellCommand{Stdout: "myPlugin version 1.2.3"}, 266 cluster.ShellCommand{Stdout: "myPlugin version 1.2.3"}, 267 }, 268 } 269 270 // write history file using test cluster directories 271 testCluster := testutils.SetupTestCluster() 272 testCluster.Executor = &executor 273 oldWd, err = os.Getwd() 274 Expect(err).ToNot(HaveOccurred()) 275 err = os.Chdir(tempDir) 276 Expect(err).ToNot(HaveOccurred()) 277 mdd = filepath.Join(tempDir, testCluster.GetDirForContent(-1)) 278 err = os.MkdirAll(mdd, 0777) 279 Expect(err).ToNot(HaveOccurred()) 280 historyPath := filepath.Join(mdd, "gpbackup_history.yaml") 281 _ = os.Remove(historyPath) // make sure no previous copy 282 err = ioutil.WriteFile(historyPath, []byte(sampleBackupHistory), 0777) 283 Expect(err).ToNot(HaveOccurred()) 284 285 // create backup config file 286 configDir := filepath.Join(mdd, "backups/20170101/20170101010101/") 287 _ = os.MkdirAll(configDir, 0777) 288 configPath := filepath.Join(configDir, "gpbackup_20170101010101_config.yaml") 289 err = ioutil.WriteFile(configPath, []byte(sampleBackupConfig), 0777) 290 Expect(err).ToNot(HaveOccurred()) 291 292 restore.SetVersion("1.11.0+dev.28.g10571fd") 293 }) 294 AfterEach(func() { 295 _ = os.Chdir(oldWd) 296 err := os.RemoveAll(tempDir) 297 Expect(err).To(Not(HaveOccurred())) 298 _ = os.Remove(testConfigPath) 299 confDir := filepath.Dir(testConfigPath) 300 confFileName := filepath.Base(testConfigPath) 301 files, _ := ioutil.ReadDir(confDir) 302 for _, f := range files { 303 match, _ := filepath.Match("*"+confFileName+"*", f.Name()) 304 if match { 305 _ = os.Remove(confDir + "/" + f.Name()) 306 } 307 } 308 }) 309 Describe("RecoverMetadataFilesUsingPlugin", func() { 310 It("proceed without warning when plugin version is found", func() { 311 _ = cmdFlags.Set(options.TIMESTAMP, "20180415154238") 312 restore.RecoverMetadataFilesUsingPlugin() 313 Expect(string(logfile.Contents())).ToNot(ContainSubstring("cannot recover plugin version")) 314 }) 315 It("logs warning when plugin version not found", func() { 316 _ = cmdFlags.Set(options.TIMESTAMP, "20170415154408") 317 restore.RecoverMetadataFilesUsingPlugin() 318 Expect(string(logfile.Contents())).To(ContainSubstring("cannot recover plugin version")) 319 }) 320 }) 321 Describe("FindHistoricalPluginVersion", func() { 322 It("finds plugin version", func() { 323 resultPluginVersion := restore.FindHistoricalPluginVersion("20180415154238") 324 Expect(resultPluginVersion).To(Equal("99.99.9999")) 325 }) 326 }) 327 }) 328 })