github.com/mithrandie/csvq@v1.18.1/lib/query/main_test.go (about) 1 package query 2 3 import ( 4 "context" 5 "io" 6 "os" 7 "path/filepath" 8 "reflect" 9 "runtime" 10 "testing" 11 "time" 12 13 "github.com/mithrandie/csvq/lib/file" 14 "github.com/mithrandie/csvq/lib/option" 15 "github.com/mithrandie/csvq/lib/value" 16 ) 17 18 type syncMapStruct interface { 19 SortedKeys() []string 20 LoadDirect(string) (interface{}, bool) 21 } 22 23 func SyncMapEqual(m1 syncMapStruct, m2 syncMapStruct) bool { 24 mkeys := m1.SortedKeys() 25 vlist := make([]interface{}, 0, len(mkeys)) 26 for _, key := range mkeys { 27 v, _ := m1.LoadDirect(key) 28 vlist = append(vlist, v) 29 } 30 31 m2keys := m2.SortedKeys() 32 vlist2 := make([]interface{}, 0, len(m2keys)) 33 for _, key := range m2keys { 34 v, _ := m2.LoadDirect(key) 35 vlist2 = append(vlist2, v) 36 } 37 return reflect.DeepEqual(vlist, vlist2) 38 } 39 40 func BlockScopeListEqual(s1 []BlockScope, s2 []BlockScope) bool { 41 if len(s1) != len(s2) { 42 return false 43 } 44 for i := range s1 { 45 if !SyncMapEqual(s1[i].Variables, s2[i].Variables) { 46 return false 47 } 48 if !SyncMapEqual(s1[i].TemporaryTables, s2[i].TemporaryTables) { 49 return false 50 } 51 if !SyncMapEqual(s1[i].Cursors, s2[i].Cursors) { 52 return false 53 } 54 if !reflect.DeepEqual(s1[i].Functions, s2[i].Functions) { 55 return false 56 } 57 } 58 return true 59 } 60 61 func NodeScopeListEqual(s1 []NodeScope, s2 []NodeScope) bool { 62 if len(s1) != len(s2) { 63 return false 64 } 65 for i := range s1 { 66 if !reflect.DeepEqual(s1[i].inlineTables, s2[i].inlineTables) { 67 return false 68 } 69 if !reflect.DeepEqual(s1[i].aliases, s2[i].aliases) { 70 return false 71 } 72 } 73 return true 74 } 75 76 func GetTestFilePath(filename string) string { 77 return filepath.Join(TestDir, filename) 78 } 79 80 var tempdir, _ = filepath.Abs(os.TempDir()) 81 var TestDir = filepath.Join(tempdir, "csvq_query_test") 82 var TestDataDir string 83 var CompletionTestDir = filepath.Join(TestDir, "completion") 84 var CompletionTestSubDir = filepath.Join(TestDir, "completion", "sub") 85 var TestLocation = "UTC" 86 var NowForTest = time.Date(2012, 2, 3, 9, 18, 15, 0, GetTestLocation()) 87 88 var TestTx, _ = NewTransaction(context.Background(), file.DefaultWaitTimeout, file.DefaultRetryDelay, NewSession()) 89 90 func GetTestLocation() *time.Location { 91 l, _ := time.LoadLocation(TestLocation) 92 return l 93 } 94 95 func GetWD() string { 96 wdir, _ := os.Getwd() 97 return wdir 98 } 99 100 func TestMain(m *testing.M) { 101 os.Exit(run(m)) 102 } 103 104 func run(m *testing.M) int { 105 defer teardown() 106 107 setup() 108 return m.Run() 109 } 110 111 func setup() { 112 if _, err := os.Stat(TestDir); err == nil { 113 _ = os.RemoveAll(TestDir) 114 } 115 if _, err := os.Stat(TestDir); os.IsNotExist(err) { 116 _ = os.Mkdir(TestDir, 0755) 117 } 118 119 option.TestTime = NowForTest 120 121 TestDataDir = filepath.Join(GetWD(), "..", "..", "testdata", "csv") 122 123 r, _ := os.Open(filepath.Join(TestDataDir, "empty.txt")) 124 os.Stdin = r 125 126 _ = copyfile(filepath.Join(TestDir, "table_sjis.csv"), filepath.Join(TestDataDir, "table_sjis.csv")) 127 _ = copyfile(filepath.Join(TestDir, "table_noheader.csv"), filepath.Join(TestDataDir, "table_noheader.csv")) 128 _ = copyfile(filepath.Join(TestDir, "table_broken.csv"), filepath.Join(TestDataDir, "table_broken.csv")) 129 _ = copyfile(filepath.Join(TestDir, "table1.csv"), filepath.Join(TestDataDir, "table1.csv")) 130 _ = copyfile(filepath.Join(TestDir, "table1_bom.csv"), filepath.Join(TestDataDir, "table1_bom.csv")) 131 _ = copyfile(filepath.Join(TestDir, "table1b.csv"), filepath.Join(TestDataDir, "table1b.csv")) 132 _ = copyfile(filepath.Join(TestDir, "table2.csv"), filepath.Join(TestDataDir, "table2.csv")) 133 _ = copyfile(filepath.Join(TestDir, "table4.csv"), filepath.Join(TestDataDir, "table4.csv")) 134 _ = copyfile(filepath.Join(TestDir, "table5.csv"), filepath.Join(TestDataDir, "table5.csv")) 135 _ = copyfile(filepath.Join(TestDir, "group_table.csv"), filepath.Join(TestDataDir, "group_table.csv")) 136 _ = copyfile(filepath.Join(TestDir, "insert_query.csv"), filepath.Join(TestDataDir, "table1.csv")) 137 _ = copyfile(filepath.Join(TestDir, "update_query.csv"), filepath.Join(TestDataDir, "table1.csv")) 138 _ = copyfile(filepath.Join(TestDir, "delete_query.csv"), filepath.Join(TestDataDir, "table1.csv")) 139 _ = copyfile(filepath.Join(TestDir, "add_columns.csv"), filepath.Join(TestDataDir, "table1.csv")) 140 _ = copyfile(filepath.Join(TestDir, "drop_columns.csv"), filepath.Join(TestDataDir, "table1.csv")) 141 _ = copyfile(filepath.Join(TestDir, "rename_column.csv"), filepath.Join(TestDataDir, "table1.csv")) 142 _ = copyfile(filepath.Join(TestDir, "updated_file_1.csv"), filepath.Join(TestDataDir, "table1.csv")) 143 _ = copyfile(filepath.Join(TestDir, "dup_name.csv"), filepath.Join(TestDataDir, "dup_name.csv")) 144 _ = copyfile(filepath.Join(TestDir, "table_empty.csv"), filepath.Join(TestDataDir, "table_empty.csv")) 145 146 _ = copyfile(filepath.Join(TestDir, "table3.tsv"), filepath.Join(TestDataDir, "table3.tsv")) 147 _ = copyfile(filepath.Join(TestDir, "dup_name.tsv"), filepath.Join(TestDataDir, "dup_name.tsv")) 148 149 _ = copyfile(filepath.Join(TestDir, "table.json"), filepath.Join(TestDataDir, "table.json")) 150 _ = copyfile(filepath.Join(TestDir, "table_h.json"), filepath.Join(TestDataDir, "table_h.json")) 151 _ = copyfile(filepath.Join(TestDir, "table_a.json"), filepath.Join(TestDataDir, "table_a.json")) 152 153 _ = copyfile(filepath.Join(TestDir, "table7.jsonl"), filepath.Join(TestDataDir, "table7.jsonl")) 154 155 _ = copyfile(filepath.Join(TestDir, "table6.ltsv"), filepath.Join(TestDataDir, "table6.ltsv")) 156 _ = copyfile(filepath.Join(TestDir, "table6_bom.ltsv"), filepath.Join(TestDataDir, "table6_bom.ltsv")) 157 158 _ = copyfile(filepath.Join(TestDir, "fixed_length.txt"), filepath.Join(TestDataDir, "fixed_length.txt")) 159 _ = copyfile(filepath.Join(TestDir, "fixed_length_bom.txt"), filepath.Join(TestDataDir, "fixed_length_bom.txt")) 160 _ = copyfile(filepath.Join(TestDir, "fixed_length_sl.txt"), filepath.Join(TestDataDir, "fixed_length_sl.txt")) 161 162 _ = copyfile(filepath.Join(TestDir, "autoselect"), filepath.Join(TestDataDir, "autoselect")) 163 164 _ = copyfile(filepath.Join(TestDir, "source.sql"), filepath.Join(filepath.Join(GetWD(), "..", "..", "testdata"), "source.sql")) 165 _ = copyfile(filepath.Join(TestDir, "source_syntaxerror.sql"), filepath.Join(filepath.Join(GetWD(), "..", "..", "testdata"), "source_syntaxerror.sql")) 166 167 _ = os.Setenv("CSVQ_TEST_ENV", "foo") 168 169 if _, err := os.Stat(CompletionTestDir); os.IsNotExist(err) { 170 _ = os.Mkdir(CompletionTestDir, 0755) 171 } 172 if _, err := os.Stat(CompletionTestSubDir); os.IsNotExist(err) { 173 _ = os.Mkdir(CompletionTestSubDir, 0755) 174 } 175 _ = copyfile(filepath.Join(CompletionTestDir, "table1.csv"), filepath.Join(TestDataDir, "table1.csv")) 176 _ = copyfile(filepath.Join(CompletionTestDir, ".table1.csv"), filepath.Join(TestDataDir, "table1.csv")) 177 _ = copyfile(filepath.Join(CompletionTestDir, "source.sql"), filepath.Join(filepath.Join(GetWD(), "..", "..", "testdata"), "source.sql")) 178 _ = copyfile(filepath.Join(CompletionTestSubDir, "table2.csv"), filepath.Join(TestDataDir, "table2.csv")) 179 180 Version = "v1.0.0" 181 TestTx.Session.SetStdout(NewDiscard()) 182 TestTx.Session.SetStderr(NewDiscard()) 183 initFlag(TestTx.Flags) 184 } 185 186 func teardown() { 187 if _, err := os.Stat(TestDir); err == nil { 188 _ = os.RemoveAll(TestDir) 189 } 190 } 191 192 func initFlag(flags *option.Flags) { 193 cpu := runtime.NumCPU() / 2 194 if cpu < 1 { 195 cpu = 1 196 } 197 198 flags.Repository = "." 199 flags.DatetimeFormat = []string{} 200 flags.AnsiQuotes = false 201 flags.StrictEqual = false 202 flags.WaitTimeout = 15 203 flags.ImportOptions = option.NewImportOptions() 204 flags.ExportOptions = option.NewExportOptions() 205 flags.Quiet = false 206 flags.LimitRecursion = 5 207 flags.CPU = cpu 208 flags.Stats = false 209 flags.SetColor(false) 210 _ = flags.SetLocation(TestLocation) 211 } 212 213 func copyfile(dstfile string, srcfile string) error { 214 src, err := os.Open(srcfile) 215 if err != nil { 216 return err 217 } 218 defer func() { _ = src.Close() }() 219 220 dst, err := os.Create(dstfile) 221 if err != nil { 222 return err 223 } 224 defer func() { _ = dst.Close() }() 225 226 _, err = io.Copy(dst, src) 227 if err != nil { 228 return err 229 } 230 231 return nil 232 } 233 234 const ( 235 scopeNameVariables = "v" 236 scopeNameTempTables = "t" 237 scopeNameCursors = "c" 238 scopeNameFunctions = "f" 239 scopeNameInlineTables = "i" 240 scopeNameAliases = "a" 241 ) 242 243 func GenerateReferenceScope(blocks []map[string]map[string]interface{}, nodes []map[string]map[string]interface{}, now time.Time, records []ReferenceRecord) *ReferenceScope { 244 rs := NewReferenceScope(TestTx) 245 for i := 1; i < len(blocks); i++ { 246 rs = rs.CreateChild() 247 } 248 249 for i := range blocks { 250 for n := range blocks[i] { 251 for k, v := range blocks[i][n] { 252 switch n { 253 case scopeNameVariables: 254 rs.Blocks[i].Variables.Store(k, v.(value.Primary)) 255 case scopeNameTempTables: 256 rs.Blocks[i].TemporaryTables.Store(k, v.(*View)) 257 case scopeNameCursors: 258 rs.Blocks[i].Cursors.Store(k, v.(*Cursor)) 259 case scopeNameFunctions: 260 rs.Blocks[i].Functions.Store(k, v.(*UserDefinedFunction)) 261 } 262 } 263 } 264 } 265 266 if nodes != nil { 267 ns := make([]NodeScope, len(nodes)) 268 for i := range nodes { 269 ns[i] = GetNodeScope() 270 for n := range nodes[i] { 271 for k, v := range nodes[i][n] { 272 switch n { 273 case scopeNameInlineTables: 274 ns[i].inlineTables[k] = v.(*View) 275 case scopeNameAliases: 276 ns[i].aliases[k] = v.(string) 277 } 278 } 279 } 280 } 281 rs.nodes = ns 282 } 283 284 if !now.IsZero() { 285 rs.now = now 286 } 287 288 if records != nil { 289 rs.Records = records 290 } 291 292 return rs 293 } 294 295 func GenerateViewMap(values []*View) ViewMap { 296 m := NewViewMap() 297 for _, v := range values { 298 m.Store(v.FileInfo.IdentifiedPath(), v) 299 } 300 return m 301 } 302 303 func GenerateCursorMap(values []*Cursor) CursorMap { 304 m := NewCursorMap() 305 for _, v := range values { 306 m.Store(v.Name, v) 307 } 308 return m 309 } 310 311 func GenerateUserDefinedFunctionMap(values []*UserDefinedFunction) UserDefinedFunctionMap { 312 m := NewUserDefinedFunctionMap() 313 for _, v := range values { 314 m.Store(v.Name.Literal, v) 315 } 316 return m 317 } 318 319 func GenerateStatementMap(values []*PreparedStatement) PreparedStatementMap { 320 m := NewPreparedStatementMap() 321 for _, v := range values { 322 m.Store(v.Name, v) 323 } 324 return m 325 } 326 327 var ( 328 testLetterRunes = []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 329 ) 330 331 func randomStr(length int) string { 332 s := make([]rune, length) 333 for i := 0; i < length; i++ { 334 s[i] = testLetterRunes[option.GetRand().Intn(len(testLetterRunes))] 335 } 336 return string(s) 337 }