github.com/mithrandie/csvq@v1.18.1/lib/query/view_map_test.go (about) 1 package query 2 3 import ( 4 "context" 5 "reflect" 6 "strings" 7 "testing" 8 9 "github.com/mithrandie/csvq/lib/parser" 10 "github.com/mithrandie/csvq/lib/value" 11 ) 12 13 var viewMapExistsTests = []struct { 14 Name string 15 Path string 16 Result bool 17 }{ 18 { 19 Name: "ViewMap Exists", 20 Path: strings.ToUpper("/path/to/table1.csv"), 21 Result: true, 22 }, 23 { 24 Name: "ViewMap Exists Not Exist", 25 Path: strings.ToUpper("/path/to/notexist.csv"), 26 Result: false, 27 }, 28 } 29 30 func TestViewMap_Exists(t *testing.T) { 31 viewMap := GenerateViewMap([]*View{ 32 { 33 Header: NewHeader("table1", []string{"column1", "column2"}), 34 RecordSet: []Record{}, 35 FileInfo: &FileInfo{ 36 Path: "/path/to/table1.csv", 37 Delimiter: ',', 38 }, 39 }, 40 }) 41 42 for _, v := range viewMapExistsTests { 43 result := viewMap.Exists(v.Path) 44 if result != v.Result { 45 t.Errorf("%s: result = %t, want %t", v.Name, result, v.Result) 46 } 47 } 48 } 49 50 var viewMapGetTests = []struct { 51 Name string 52 Path string 53 Result *View 54 Error string 55 }{ 56 { 57 Name: "ViewMap Get", 58 Path: strings.ToUpper("/path/to/table1.csv"), 59 Result: &View{ 60 Header: NewHeader("table1", []string{"column1", "column2"}), 61 RecordSet: []Record{ 62 NewRecord([]value.Primary{ 63 value.NewString("1"), 64 value.NewString("str1"), 65 }), 66 NewRecord([]value.Primary{ 67 value.NewString("2"), 68 value.NewString("str2"), 69 }), 70 }, 71 FileInfo: &FileInfo{ 72 Path: "/path/to/table1.csv", 73 Delimiter: ',', 74 }, 75 }, 76 }, 77 { 78 Name: "ViewMap Get Not Loaded Error", 79 Path: strings.ToUpper("/path/to/table2.csv"), 80 Error: "table not loaded", 81 }, 82 } 83 84 func TestViewMap_Get(t *testing.T) { 85 viewMap := GenerateViewMap([]*View{ 86 { 87 Header: NewHeader("table1", []string{"column1", "column2"}), 88 RecordSet: []Record{ 89 NewRecord([]value.Primary{ 90 value.NewString("1"), 91 value.NewString("str1"), 92 }), 93 NewRecord([]value.Primary{ 94 value.NewString("2"), 95 value.NewString("str2"), 96 }), 97 }, 98 FileInfo: &FileInfo{ 99 Path: "/path/to/table1.csv", 100 Delimiter: ',', 101 }, 102 }, 103 }) 104 105 for _, v := range viewMapGetTests { 106 view, err := viewMap.Get(v.Path) 107 if err != nil { 108 if len(v.Error) < 1 { 109 t.Errorf("%s: unexpected error %q", v.Name, err) 110 } else if err.Error() != v.Error { 111 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 112 } 113 continue 114 } 115 if 0 < len(v.Error) { 116 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 117 continue 118 } 119 if !reflect.DeepEqual(view, v.Result) { 120 t.Errorf("%s: view = %v, want %v", v.Name, view, v.Result) 121 } 122 } 123 } 124 125 var viewMapGetWithInternalIdTests = []struct { 126 Name string 127 Path string 128 Result *View 129 Error string 130 }{ 131 { 132 Name: "ViewMap GetWithInternalId", 133 Path: strings.ToUpper("/path/to/table1.csv"), 134 Result: &View{ 135 Header: NewHeaderWithId("table1", []string{"column1", "column2"}), 136 RecordSet: []Record{ 137 NewRecordWithId(0, []value.Primary{ 138 value.NewString("1"), 139 value.NewString("str1"), 140 }), 141 NewRecordWithId(1, []value.Primary{ 142 value.NewString("2"), 143 value.NewString("str2"), 144 }), 145 }, 146 FileInfo: &FileInfo{ 147 Path: "/path/to/table1.csv", 148 Delimiter: ',', 149 }, 150 }, 151 }, 152 { 153 Name: "ViewMap GetWithInternalId Not Loaded Error", 154 Path: strings.ToUpper("/path/to/table2.csv"), 155 Error: "table not loaded", 156 }, 157 } 158 159 func TestViewMap_GetWithInternalId(t *testing.T) { 160 viewMap := GenerateViewMap([]*View{ 161 { 162 Header: NewHeader("table1", []string{"column1", "column2"}), 163 RecordSet: []Record{ 164 NewRecord([]value.Primary{ 165 value.NewString("1"), 166 value.NewString("str1"), 167 }), 168 NewRecord([]value.Primary{ 169 value.NewString("2"), 170 value.NewString("str2"), 171 }), 172 }, 173 FileInfo: &FileInfo{ 174 Path: "/path/to/table1.csv", 175 Delimiter: ',', 176 }, 177 }, 178 }) 179 180 for _, v := range viewMapGetWithInternalIdTests { 181 view, err := viewMap.GetWithInternalId(context.Background(), v.Path, TestTx.Flags) 182 if err != nil { 183 if len(v.Error) < 1 { 184 t.Errorf("%s: unexpected error %q", v.Name, err) 185 } else if err.Error() != v.Error { 186 t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error) 187 } 188 continue 189 } 190 if 0 < len(v.Error) { 191 t.Errorf("%s: no error, want error %q", v.Name, v.Error) 192 continue 193 } 194 if !reflect.DeepEqual(view, v.Result) { 195 t.Errorf("%s: view = %v, want %v", v.Name, view, v.Result) 196 } 197 } 198 } 199 200 var viewMapSetTests = []struct { 201 Name string 202 SetView *View 203 Result ViewMap 204 }{ 205 { 206 Name: "ViewMap Set", 207 SetView: &View{ 208 Header: NewHeader("table1", []string{"column1", "column2"}), 209 RecordSet: []Record{ 210 NewRecord([]value.Primary{ 211 value.NewString("1"), 212 value.NewString("str1"), 213 }), 214 NewRecord([]value.Primary{ 215 value.NewString("2"), 216 value.NewString("str2"), 217 }), 218 }, 219 FileInfo: &FileInfo{ 220 Path: "/path/to/table1.csv", 221 Delimiter: ',', 222 }, 223 }, 224 Result: GenerateViewMap([]*View{ 225 { 226 Header: NewHeader("table1", []string{"column1", "column2"}), 227 RecordSet: []Record{ 228 NewRecord([]value.Primary{ 229 value.NewString("1"), 230 value.NewString("str1"), 231 }), 232 NewRecord([]value.Primary{ 233 value.NewString("2"), 234 value.NewString("str2"), 235 }), 236 }, 237 FileInfo: &FileInfo{ 238 Path: "/path/to/table1.csv", 239 Delimiter: ',', 240 }, 241 }, 242 }), 243 }, 244 } 245 246 func TestViewMap_Set(t *testing.T) { 247 viewMap := NewViewMap() 248 249 for _, v := range viewMapSetTests { 250 viewMap.Set(v.SetView) 251 if !SyncMapEqual(viewMap, v.Result) { 252 t.Errorf("%s: map = %v, want %v", v.Name, viewMap, v.Result) 253 } 254 } 255 } 256 257 var viewMapDisposeTemporaryTable = []struct { 258 Name string 259 Table parser.Identifier 260 Result ViewMap 261 OK bool 262 }{ 263 { 264 Name: "ViewMap DisposeTemporaryTable", 265 Table: parser.Identifier{Literal: "/path/to/table1.csv"}, 266 Result: GenerateViewMap([]*View{ 267 { 268 Header: NewHeader("table1", []string{"column1", "column2"}), 269 RecordSet: []Record{ 270 NewRecord([]value.Primary{ 271 value.NewString("1"), 272 value.NewString("str1"), 273 }), 274 NewRecord([]value.Primary{ 275 value.NewString("2"), 276 value.NewString("str2"), 277 }), 278 }, 279 FileInfo: &FileInfo{ 280 Path: "/path/to/table2.csv", 281 Delimiter: ',', 282 }, 283 }, 284 }), 285 OK: true, 286 }, 287 { 288 Name: "ViewMap DisposeTemporaryTable Not Temporary Table", 289 Table: parser.Identifier{Literal: "/path/to/table2.csv"}, 290 OK: false, 291 }, 292 { 293 Name: "ViewMap DisposeTemporaryTable Undeclared Error", 294 Table: parser.Identifier{Literal: "/path/to/undef.csv"}, 295 OK: false, 296 }, 297 } 298 299 func TestViewMap_DisposeTemporaryTable(t *testing.T) { 300 viewMap := GenerateViewMap([]*View{ 301 { 302 Header: NewHeader("table1", []string{"column1", "column2"}), 303 RecordSet: []Record{ 304 NewRecord([]value.Primary{ 305 value.NewString("1"), 306 value.NewString("str1"), 307 }), 308 NewRecord([]value.Primary{ 309 value.NewString("2"), 310 value.NewString("str2"), 311 }), 312 }, 313 FileInfo: &FileInfo{ 314 Path: "/path/to/table1.csv", 315 Delimiter: ',', 316 ViewType: ViewTypeTemporaryTable, 317 }, 318 }, 319 { 320 Header: NewHeader("table1", []string{"column1", "column2"}), 321 RecordSet: []Record{ 322 NewRecord([]value.Primary{ 323 value.NewString("1"), 324 value.NewString("str1"), 325 }), 326 NewRecord([]value.Primary{ 327 value.NewString("2"), 328 value.NewString("str2"), 329 }), 330 }, 331 FileInfo: &FileInfo{ 332 Path: "/path/to/table2.csv", 333 Delimiter: ',', 334 }, 335 }, 336 }) 337 338 for _, v := range viewMapDisposeTemporaryTable { 339 ok := viewMap.DisposeTemporaryTable(v.Table) 340 if ok != v.OK { 341 t.Errorf("%s: result = %t, want %t", v.Name, ok, v.OK) 342 } 343 if ok && v.OK && !SyncMapEqual(viewMap, v.Result) { 344 t.Errorf("%s: map = %v, want %v", v.Name, viewMap, v.Result) 345 } 346 } 347 } 348 349 func TestViewMap_Clear(t *testing.T) { 350 viewMap := GenerateViewMap([]*View{ 351 { 352 Header: NewHeader("table1", []string{"column1", "column2"}), 353 RecordSet: []Record{ 354 NewRecord([]value.Primary{ 355 value.NewString("1"), 356 value.NewString("str1"), 357 }), 358 NewRecord([]value.Primary{ 359 value.NewString("2"), 360 value.NewString("str2"), 361 }), 362 }, 363 FileInfo: &FileInfo{ 364 Path: "/path/to/table1.csv", 365 Delimiter: ',', 366 ViewType: ViewTypeTemporaryTable, 367 }, 368 }, 369 { 370 Header: NewHeader("table1", []string{"column1", "column2"}), 371 RecordSet: []Record{ 372 NewRecord([]value.Primary{ 373 value.NewString("1"), 374 value.NewString("str1"), 375 }), 376 NewRecord([]value.Primary{ 377 value.NewString("2"), 378 value.NewString("str2"), 379 }), 380 }, 381 FileInfo: &FileInfo{ 382 Path: "/path/to/table2.csv", 383 Delimiter: ',', 384 }, 385 }, 386 }) 387 388 expect := NewViewMap() 389 390 _ = viewMap.Clean(TestTx.FileContainer) 391 if !SyncMapEqual(viewMap, expect) { 392 t.Errorf("result = %v, want %v", viewMap, expect) 393 } 394 } 395 396 var viewMapGetWithInternalIdBench = generateViewMapGetWithInternalIdBenchViewMap() 397 398 func generateViewMapGetWithInternalIdBenchViewMap() ViewMap { 399 m := GenerateViewMap([]*View{{ 400 Header: NewHeader("bench_view", []string{"c1", "c2", "c3", "c4"}), 401 FileInfo: &FileInfo{ 402 Path: "bench_view", 403 }, 404 }}) 405 view, _ := m.Load("BENCH_VIEW") 406 view.RecordSet = make(RecordSet, 10000) 407 for i := 0; i < 10000; i++ { 408 view.RecordSet[i] = NewRecord([]value.Primary{ 409 value.NewInteger(1), 410 value.NewInteger(2), 411 value.NewInteger(3), 412 value.NewInteger(4), 413 }) 414 } 415 return m 416 } 417 418 func BenchmarkViewMap_GetWithInternalId(b *testing.B) { 419 for i := 0; i < b.N; i++ { 420 _, _ = viewMapGetWithInternalIdBench.GetWithInternalId(context.Background(), strings.ToUpper("BENCH_VIEW"), TestTx.Flags) 421 } 422 }