github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/export_test.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "bufio" 19 "context" 20 "os" 21 "testing" 22 23 "github.com/prashantv/gostub" 24 "github.com/smartystreets/goconvey/convey" 25 26 "github.com/matrixorigin/matrixone/pkg/common/moerr" 27 "github.com/matrixorigin/matrixone/pkg/container/types" 28 "github.com/matrixorigin/matrixone/pkg/defines" 29 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 30 ) 31 32 var colName1, colName2 = "DATABASE()", "VARIABLE_VALUE" 33 34 func Test_initExportFileParam(t *testing.T) { 35 var oq = &outputQueue{ 36 mrs: &MysqlResultSet{}, 37 ep: &ExportConfig{ 38 userConfig: &tree.ExportParam{ 39 Lines: &tree.Lines{ 40 TerminatedBy: &tree.Terminated{}, 41 }, 42 Fields: &tree.Fields{ 43 Terminated: &tree.Terminated{}, 44 EnclosedBy: &tree.EnclosedBy{}, 45 EscapedBy: &tree.EscapedBy{}, 46 }, 47 }, 48 }, 49 } 50 initExportFileParam(oq.ep, oq.mrs) 51 52 col1 := new(MysqlColumn) 53 col1.SetName(colName1) 54 col2 := new(MysqlColumn) 55 col2.SetName(colName2) 56 oq.mrs.AddColumn(col1) 57 oq.mrs.AddColumn(col2) 58 59 oq.ep.userConfig.ForceQuote = append(oq.ep.userConfig.ForceQuote, colName1) 60 oq.mrs.Name2Index[colName1] = 0 61 initExportFileParam(oq.ep, oq.mrs) 62 } 63 64 func Test_openNewFile(t *testing.T) { 65 convey.Convey("openNewFile failed", t, func() { 66 var oq = &outputQueue{ 67 mrs: &MysqlResultSet{}, 68 ep: &ExportConfig{ 69 userConfig: &tree.ExportParam{ 70 Lines: &tree.Lines{ 71 TerminatedBy: &tree.Terminated{}, 72 }, 73 Fields: &tree.Fields{ 74 Terminated: &tree.Terminated{}, 75 EnclosedBy: &tree.EnclosedBy{}, 76 EscapedBy: &tree.EscapedBy{}, 77 }, 78 Header: true, 79 FilePath: "test/export.csv", 80 }, 81 }, 82 } 83 stubs := gostub.StubFunc(&OpenFile, nil, moerr.NewInternalError(context.TODO(), "can not open file")) 84 defer stubs.Reset() 85 convey.So(openNewFile(context.TODO(), oq.ep, oq.mrs), convey.ShouldNotBeNil) 86 }) 87 88 convey.Convey("openNewFile succ", t, func() { 89 var oq = &outputQueue{ 90 mrs: &MysqlResultSet{}, 91 ep: &ExportConfig{ 92 userConfig: &tree.ExportParam{ 93 Lines: &tree.Lines{ 94 TerminatedBy: &tree.Terminated{}, 95 }, 96 Fields: &tree.Fields{ 97 Terminated: &tree.Terminated{}, 98 EnclosedBy: &tree.EnclosedBy{}, 99 EscapedBy: &tree.EscapedBy{}, 100 }, 101 Header: true, 102 FilePath: "test/export.csv", 103 }, 104 LineSize: 1, 105 }, 106 } 107 col1 := new(MysqlColumn) 108 col1.SetName(colName1) 109 col2 := new(MysqlColumn) 110 col2.SetName(colName2) 111 oq.mrs.AddColumn(col1) 112 oq.mrs.AddColumn(col2) 113 114 var file = &os.File{} 115 stubs := gostub.StubFunc(&OpenFile, file, nil) 116 defer stubs.Reset() 117 118 stubs = gostub.StubFunc(&writeDataToCSVFile, nil) 119 defer stubs.Reset() 120 121 convey.So(openNewFile(context.TODO(), oq.ep, oq.mrs), convey.ShouldBeNil) 122 }) 123 } 124 125 func Test_formatOutputString(t *testing.T) { 126 convey.Convey("openNewFile failed", t, func() { 127 var oq = &outputQueue{ 128 mrs: &MysqlResultSet{}, 129 ep: &ExportConfig{ 130 userConfig: &tree.ExportParam{ 131 Lines: &tree.Lines{ 132 TerminatedBy: &tree.Terminated{}, 133 }, 134 Fields: &tree.Fields{ 135 Terminated: &tree.Terminated{}, 136 EnclosedBy: &tree.EnclosedBy{}, 137 EscapedBy: &tree.EscapedBy{}, 138 }, 139 Header: true, 140 FilePath: "test/export.csv", 141 }, 142 LineSize: 1, 143 }, 144 } 145 stubs := gostub.StubFunc(&writeDataToCSVFile, moerr.NewInternalError(context.TODO(), "write err")) 146 defer stubs.Reset() 147 convey.So(formatOutputString(oq, nil, nil, '\n', true), convey.ShouldNotBeNil) 148 149 stubs = gostub.StubFunc(&writeDataToCSVFile, nil) 150 defer stubs.Reset() 151 convey.So(formatOutputString(oq, nil, nil, '\n', true), convey.ShouldBeNil) 152 }) 153 } 154 155 func Test_writeToCSVFile(t *testing.T) { 156 convey.Convey("writeToCSVFile case", t, func() { 157 var oq = &outputQueue{ 158 mrs: &MysqlResultSet{}, 159 ep: &ExportConfig{ 160 userConfig: &tree.ExportParam{ 161 Lines: &tree.Lines{ 162 TerminatedBy: &tree.Terminated{}, 163 }, 164 Fields: &tree.Fields{ 165 Terminated: &tree.Terminated{}, 166 EnclosedBy: &tree.EnclosedBy{}, 167 EscapedBy: &tree.EscapedBy{}, 168 }, 169 Header: true, 170 FilePath: "test/export.csv", 171 }, 172 LineSize: 1, 173 Writer: &bufio.Writer{}, 174 }, 175 } 176 var output = []byte{'1', '2'} 177 oq.ep.userConfig.MaxFileSize = 1 178 179 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 180 181 oq.ep.Rows = 1 182 stubs := gostub.StubFunc(&Flush, moerr.NewInternalError(context.TODO(), "Flush error")) 183 defer stubs.Reset() 184 185 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 186 187 stubs = gostub.StubFunc(&Flush, nil) 188 defer stubs.Reset() 189 190 stubs = gostub.StubFunc(&Seek, int64(0), moerr.NewInternalError(context.TODO(), "Seek error")) 191 defer stubs.Reset() 192 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 193 194 stubs = gostub.StubFunc(&Seek, int64(0), nil) 195 defer stubs.Reset() 196 stubs = gostub.StubFunc(&Read, 0, moerr.NewInternalError(context.TODO(), "Read error")) 197 defer stubs.Reset() 198 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 199 200 stubs = gostub.StubFunc(&Read, 1, nil) 201 defer stubs.Reset() 202 203 stubs = gostub.StubFunc(&Truncate, moerr.NewInternalError(context.TODO(), "Truncate error")) 204 defer stubs.Reset() 205 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 206 207 stubs = gostub.StubFunc(&Truncate, nil) 208 defer stubs.Reset() 209 stubs = gostub.StubFunc(&Close, moerr.NewInternalError(context.TODO(), "Close error")) 210 defer stubs.Reset() 211 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 212 213 stubs = gostub.StubFunc(&Close, nil) 214 defer stubs.Reset() 215 stubs = gostub.StubFunc(&openNewFile, moerr.NewInternalError(context.TODO(), "openNewFile error")) 216 defer stubs.Reset() 217 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 218 219 stubs = gostub.StubFunc(&openNewFile, nil) 220 defer stubs.Reset() 221 stubs = gostub.StubFunc(&writeDataToCSVFile, moerr.NewInternalError(context.TODO(), "writeDataToCSVFile error")) 222 defer stubs.Reset() 223 convey.So(writeToCSVFile(oq, output), convey.ShouldNotBeNil) 224 225 stubs = gostub.StubFunc(&writeDataToCSVFile, nil) 226 defer stubs.Reset() 227 convey.So(writeToCSVFile(oq, output), convey.ShouldBeNil) 228 }) 229 } 230 231 func Test_writeDataToCSVFile(t *testing.T) { 232 convey.Convey("writeDataToCSVFile case", t, func() { 233 var oq = &outputQueue{ 234 mrs: &MysqlResultSet{}, 235 ep: &ExportConfig{ 236 userConfig: &tree.ExportParam{ 237 Lines: &tree.Lines{ 238 TerminatedBy: &tree.Terminated{}, 239 }, 240 Fields: &tree.Fields{ 241 Terminated: &tree.Terminated{}, 242 EnclosedBy: &tree.EnclosedBy{}, 243 EscapedBy: &tree.EscapedBy{}, 244 }, 245 Header: true, 246 FilePath: "test/export.csv", 247 }, 248 LineSize: 1, 249 Writer: &bufio.Writer{}, 250 }, 251 } 252 var output = []byte{'1', '2'} 253 stubs := gostub.StubFunc(&Write, 0, moerr.NewInternalError(context.TODO(), "writeDataToCSVFile error")) 254 defer stubs.Reset() 255 256 convey.So(writeDataToCSVFile(oq.ep, output), convey.ShouldNotBeNil) 257 258 stubs = gostub.StubFunc(&Write, len(output), nil) 259 defer stubs.Reset() 260 convey.So(writeDataToCSVFile(oq.ep, output), convey.ShouldBeNil) 261 262 }) 263 } 264 265 func Test_exportDataToCSVFile(t *testing.T) { 266 convey.Convey("exportDataToCSVFile succ", t, func() { 267 var oq = &outputQueue{ 268 mrs: &MysqlResultSet{}, 269 ep: &ExportConfig{ 270 userConfig: &tree.ExportParam{ 271 Lines: &tree.Lines{ 272 TerminatedBy: &tree.Terminated{}, 273 }, 274 Fields: &tree.Fields{ 275 Terminated: &tree.Terminated{}, 276 EnclosedBy: &tree.EnclosedBy{}, 277 EscapedBy: &tree.EscapedBy{}, 278 }, 279 Header: true, 280 FilePath: "test/export.csv", 281 }, 282 LineSize: 1, 283 Writer: &bufio.Writer{}, 284 }, 285 } 286 287 var col = make([]MysqlColumn, 13) 288 col[5].flag = 0 289 col[6].flag = 1 << 5 290 var colType = []defines.MysqlType{defines.MYSQL_TYPE_YEAR, defines.MYSQL_TYPE_YEAR, defines.MYSQL_TYPE_YEAR, defines.MYSQL_TYPE_SHORT, defines.MYSQL_TYPE_DOUBLE, 291 defines.MYSQL_TYPE_LONGLONG, defines.MYSQL_TYPE_LONGLONG, defines.MYSQL_TYPE_VARCHAR, defines.MYSQL_TYPE_DATE, defines.MYSQL_TYPE_DATETIME, 292 defines.MYSQL_TYPE_BOOL, defines.MYSQL_TYPE_DECIMAL, defines.MYSQL_TYPE_JSON} 293 for i := 0; i < len(col); i++ { 294 col[i].SetColumnType(colType[i]) 295 oq.mrs.AddColumn(&col[i]) 296 } 297 var data = make([]interface{}, len(col)) 298 data[1] = 0 299 data[2] = 1 300 data[3] = 1 301 data[4] = 1.0 302 data[5] = 1 303 data[6] = 1 304 data[7] = []byte{1} 305 data[8] = types.Date(1) 306 data[9] = "2022-02-28 23:59:59.9999" 307 data[10] = true 308 data[11] = 1.2 309 data[12], _ = types.ParseStringToByteJson(`{"a":1}`) 310 311 oq.mrs.AddRow(data) 312 313 oq.ep.Symbol = make([][]byte, len(col)) 314 oq.ep.ColumnFlag = make([]bool, len(col)) 315 316 stubs := gostub.StubFunc(&formatOutputString, nil) 317 defer stubs.Reset() 318 319 convey.So(exportDataToCSVFile(oq), convey.ShouldBeNil) 320 }) 321 322 convey.Convey("exportDataToCSVFile fail", t, func() { 323 var oq = &outputQueue{ 324 mrs: &MysqlResultSet{}, 325 ep: &ExportConfig{ 326 userConfig: &tree.ExportParam{ 327 Lines: &tree.Lines{ 328 TerminatedBy: &tree.Terminated{}, 329 }, 330 Fields: &tree.Fields{ 331 Terminated: &tree.Terminated{}, 332 EnclosedBy: &tree.EnclosedBy{}, 333 EscapedBy: &tree.EscapedBy{}, 334 }, 335 Header: true, 336 FilePath: "test/export.csv", 337 }, 338 LineSize: 1, 339 Writer: &bufio.Writer{}, 340 }, 341 } 342 var col = make([]MysqlColumn, 1) 343 var colType = []defines.MysqlType{defines.MYSQL_TYPE_TIMESTAMP} 344 for i := 0; i < len(col); i++ { 345 col[i].SetColumnType(colType[i]) 346 oq.mrs.AddColumn(&col[i]) 347 } 348 349 var data = make([]interface{}, len(col)) 350 data[0] = 1 351 oq.mrs.AddRow(data) 352 oq.ep.Symbol = make([][]byte, len(col)) 353 oq.ep.ColumnFlag = make([]bool, len(col)) 354 355 stubs := gostub.StubFunc(&formatOutputString, nil) 356 defer stubs.Reset() 357 358 convey.So(exportDataToCSVFile(oq), convey.ShouldBeNil) 359 }) 360 }