github.com/mithrandie/csvq@v1.18.1/lib/query/reference_scope_test.go (about)

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/mithrandie/go-text"
    11  
    12  	"github.com/mithrandie/csvq/lib/parser"
    13  	"github.com/mithrandie/csvq/lib/value"
    14  )
    15  
    16  func TestFieldIndexCache_Get(t *testing.T) {
    17  	cache := &FieldIndexCache{
    18  		limitToUseSlice: 2,
    19  		m:               nil,
    20  		exprs:           []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}},
    21  		indices:         []int{1},
    22  	}
    23  
    24  	_, ok := cache.Get(parser.FieldReference{Column: parser.Identifier{Literal: "c9"}})
    25  	if ok {
    26  		t.Error("Get() is succeeded, want to be failed")
    27  	}
    28  
    29  	expect := 1
    30  	idx, ok := cache.Get(parser.FieldReference{Column: parser.Identifier{Literal: "c1"}})
    31  	if !ok {
    32  		t.Error("Get() is failed, want to be succeeded")
    33  	}
    34  	if idx != expect {
    35  		t.Errorf("result = %d, want %d", idx, expect)
    36  	}
    37  
    38  	cache = &FieldIndexCache{
    39  		limitToUseSlice: 2,
    40  		m: map[parser.QueryExpression]int{
    41  			parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}: 1,
    42  			parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}: 2,
    43  			parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}: 3,
    44  		},
    45  		exprs:   nil,
    46  		indices: nil,
    47  	}
    48  
    49  	_, ok = cache.Get(parser.FieldReference{Column: parser.Identifier{Literal: "c9"}})
    50  	if ok {
    51  		t.Error("Get() is succeeded, want to be failed")
    52  	}
    53  
    54  	expect = 2
    55  	idx, ok = cache.Get(parser.FieldReference{Column: parser.Identifier{Literal: "c2"}})
    56  	if !ok {
    57  		t.Error("Get() is failed, want to be succeeded")
    58  	}
    59  	if idx != expect {
    60  		t.Errorf("result = %d, want %d", idx, expect)
    61  	}
    62  }
    63  
    64  func TestFieldIndexCache_Add(t *testing.T) {
    65  	cache := NewFieldIndexCache(1, 2)
    66  
    67  	cache.Add(parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}, 1)
    68  	expect := &FieldIndexCache{
    69  		limitToUseSlice: 2,
    70  		m:               nil,
    71  		exprs:           []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}},
    72  		indices:         []int{1},
    73  	}
    74  
    75  	if !reflect.DeepEqual(cache, expect) {
    76  		t.Errorf("cache = %v, want %v", cache, expect)
    77  	}
    78  
    79  	cache.Add(parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}, 2)
    80  	cache.Add(parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}, 3)
    81  	expect = &FieldIndexCache{
    82  		limitToUseSlice: 2,
    83  		m: map[parser.QueryExpression]int{
    84  			parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}: 1,
    85  			parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}: 2,
    86  			parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}: 3,
    87  		},
    88  		exprs:   nil,
    89  		indices: nil,
    90  	}
    91  
    92  	if !reflect.DeepEqual(cache, expect) {
    93  		t.Errorf("cache = %v, want %v", cache, expect)
    94  	}
    95  }
    96  
    97  var testVariablesReferenceScope = GenerateReferenceScope([]map[string]map[string]interface{}{
    98  	{
    99  		scopeNameVariables: {
   100  			"var1": value.NewInteger(1),
   101  		},
   102  	},
   103  	{
   104  		scopeNameVariables: {
   105  			"var1": value.NewInteger(2),
   106  		},
   107  	},
   108  }, nil, time.Time{}, nil)
   109  
   110  var testTemporaryTablesReferenceScope = GenerateReferenceScope([]map[string]map[string]interface{}{
   111  	{
   112  		scopeNameTempTables: {
   113  			"TEMPTABLE1": &View{
   114  				Header: NewHeader("temptable1", []string{"column1", "column2"}),
   115  				RecordSet: []Record{
   116  					NewRecord([]value.Primary{
   117  						value.NewString("1"),
   118  						value.NewString("str1"),
   119  					}),
   120  					NewRecord([]value.Primary{
   121  						value.NewString("2"),
   122  						value.NewString("str2"),
   123  					}),
   124  				},
   125  				FileInfo: &FileInfo{
   126  					Path:      "temptable1",
   127  					Delimiter: ',',
   128  					ViewType:  ViewTypeTemporaryTable,
   129  				},
   130  			},
   131  		},
   132  	},
   133  	{
   134  		scopeNameTempTables: {
   135  			"TEMPTABLE2": &View{
   136  				Header: NewHeader("temptable2", []string{"column1", "column2"}),
   137  				RecordSet: []Record{
   138  					NewRecord([]value.Primary{
   139  						value.NewString("1"),
   140  						value.NewString("str1"),
   141  					}),
   142  					NewRecord([]value.Primary{
   143  						value.NewString("2"),
   144  						value.NewString("str2"),
   145  					}),
   146  				},
   147  				FileInfo: &FileInfo{
   148  					Path:      "temptable2",
   149  					Delimiter: ',',
   150  					ViewType:  ViewTypeTemporaryTable,
   151  				},
   152  			},
   153  		},
   154  	},
   155  }, nil, time.Time{}, nil)
   156  
   157  var referenceScopeGetVariableTests = []struct {
   158  	Name   string
   159  	Expr   parser.Variable
   160  	Result value.Primary
   161  	Error  string
   162  }{
   163  	{
   164  		Name:   "ReferenceScope GetVariable",
   165  		Expr:   parser.Variable{Name: "var1"},
   166  		Result: value.NewInteger(1),
   167  	},
   168  	{
   169  		Name:  "ReferenceScope GetVariable Undeclared Error",
   170  		Expr:  parser.Variable{Name: "undef"},
   171  		Error: "variable @undef is undeclared",
   172  	},
   173  }
   174  
   175  func TestReferenceScope_GetVariable(t *testing.T) {
   176  
   177  	for _, v := range referenceScopeGetVariableTests {
   178  		result, err := testVariablesReferenceScope.GetVariable(v.Expr)
   179  		if err != nil {
   180  			if len(v.Error) < 1 {
   181  				t.Errorf("%s: unexpected error %q", v.Name, err)
   182  			} else if err.Error() != v.Error {
   183  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   184  			}
   185  			continue
   186  		}
   187  		if 0 < len(v.Error) {
   188  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   189  			continue
   190  		}
   191  		if !reflect.DeepEqual(result, v.Result) {
   192  			t.Errorf("%s: result = %s, want %s", v.Name, result, v.Result)
   193  		}
   194  	}
   195  }
   196  
   197  var referenceScopeSubstituteVariableTests = []struct {
   198  	Name        string
   199  	Expr        parser.VariableSubstitution
   200  	ResultScope *ReferenceScope
   201  	Result      value.Primary
   202  	Error       string
   203  }{
   204  	{
   205  		Name: "ReferenceScope SubstituteVariable",
   206  		Expr: parser.VariableSubstitution{
   207  			Variable: parser.Variable{Name: "var1"},
   208  			Value:    parser.NewIntegerValue(3),
   209  		},
   210  		ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{
   211  			{
   212  				scopeNameVariables: {
   213  					"var1": value.NewInteger(3),
   214  				},
   215  			},
   216  			{
   217  				scopeNameVariables: {
   218  					"var1": value.NewInteger(2),
   219  				},
   220  			},
   221  		}, nil, time.Time{}, nil),
   222  		Result: value.NewInteger(3),
   223  	},
   224  	{
   225  		Name: "ReferenceScope SubstituteVariable Undeclared Error",
   226  		Expr: parser.VariableSubstitution{
   227  			Variable: parser.Variable{Name: "var2"},
   228  			Value:    parser.NewIntegerValue(3),
   229  		},
   230  		Error: "variable @var2 is undeclared",
   231  	},
   232  }
   233  
   234  func TestReferenceScope_SubstituteVariable(t *testing.T) {
   235  	for _, v := range referenceScopeSubstituteVariableTests {
   236  		result, err := testVariablesReferenceScope.SubstituteVariable(context.Background(), v.Expr)
   237  		if err != nil {
   238  			if len(v.Error) < 1 {
   239  				t.Errorf("%s: unexpected error %q", v.Name, err)
   240  			} else if err.Error() != v.Error {
   241  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   242  			}
   243  			continue
   244  		}
   245  		if 0 < len(v.Error) {
   246  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   247  			continue
   248  		}
   249  		if !BlockScopeListEqual(testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) {
   250  			t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.Blocks, v.ResultScope.Blocks)
   251  		}
   252  		if !reflect.DeepEqual(result, v.Result) {
   253  			t.Errorf("%s: result = %v, want %v", v.Name, result, v.Result)
   254  		}
   255  	}
   256  }
   257  
   258  var referenceScopeDisposeVariableTests = []struct {
   259  	Name        string
   260  	Expr        parser.Variable
   261  	ResultScope *ReferenceScope
   262  	Error       string
   263  }{
   264  	{
   265  		Name: "ReferenceScope DisposeVariable",
   266  		Expr: parser.Variable{Name: "var1"},
   267  		ResultScope: GenerateReferenceScope([]map[string]map[string]interface{}{
   268  			{},
   269  			{
   270  				scopeNameVariables: {
   271  					"var1": value.NewInteger(2),
   272  				},
   273  			},
   274  		}, nil, time.Time{}, nil),
   275  	},
   276  	{
   277  		Name:  "ReferenceScope DisposeVariable Undeclared Error",
   278  		Expr:  parser.Variable{Name: "undef"},
   279  		Error: "variable @undef is undeclared",
   280  	},
   281  }
   282  
   283  func TestReferenceScope_DisposeVariable(t *testing.T) {
   284  	for _, v := range referenceScopeDisposeVariableTests {
   285  		err := testVariablesReferenceScope.DisposeVariable(v.Expr)
   286  		if err != nil {
   287  			if len(v.Error) < 1 {
   288  				t.Errorf("%s: unexpected error %q", v.Name, err)
   289  			} else if err.Error() != v.Error {
   290  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   291  			}
   292  			continue
   293  		}
   294  		if 0 < len(v.Error) {
   295  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   296  			continue
   297  		}
   298  		if !BlockScopeListEqual(testVariablesReferenceScope.Blocks, v.ResultScope.Blocks) {
   299  			t.Errorf("%s: blocks = %v, want %v", v.Name, testVariablesReferenceScope.Blocks, v.ResultScope.Blocks)
   300  		}
   301  	}
   302  }
   303  
   304  var referenceScopeTemporaryTableExistsTests = []struct {
   305  	Name   string
   306  	Path   string
   307  	Result bool
   308  }{
   309  	{
   310  		Name:   "ReferenceScope TemporaryTableExists",
   311  		Path:   "temptable2",
   312  		Result: true,
   313  	},
   314  	{
   315  		Name:   "ReferenceScope TemporaryTableExists Not Exist",
   316  		Path:   "notexist",
   317  		Result: false,
   318  	},
   319  }
   320  
   321  func TestReferenceScope_TemporaryTableExists(t *testing.T) {
   322  
   323  	for _, v := range referenceScopeTemporaryTableExistsTests {
   324  		result := testTemporaryTablesReferenceScope.TemporaryTableExists(v.Path)
   325  		if result != v.Result {
   326  			t.Errorf("%s: result = %t, want %t", v.Name, result, v.Result)
   327  		}
   328  	}
   329  }
   330  
   331  var referenceScopeGetTemporaryTableTests = []struct {
   332  	Name   string
   333  	Path   parser.Identifier
   334  	Result *View
   335  	Error  string
   336  }{
   337  	{
   338  		Name: "ReferenceScope GetTemporaryTable",
   339  		Path: parser.Identifier{Literal: "temptable2"},
   340  		Result: &View{
   341  			Header: NewHeader("temptable2", []string{"column1", "column2"}),
   342  			RecordSet: []Record{
   343  				NewRecord([]value.Primary{
   344  					value.NewString("1"),
   345  					value.NewString("str1"),
   346  				}),
   347  				NewRecord([]value.Primary{
   348  					value.NewString("2"),
   349  					value.NewString("str2"),
   350  				}),
   351  			},
   352  			FileInfo: &FileInfo{
   353  				Path:      "temptable2",
   354  				Delimiter: ',',
   355  				ViewType:  ViewTypeTemporaryTable,
   356  			},
   357  		},
   358  	},
   359  	{
   360  		Name:  "ReferenceScope GetTemporaryTable Not Loaded Error",
   361  		Path:  parser.Identifier{Literal: "/path/to/table9.csv"},
   362  		Error: "view /path/to/table9.csv is undeclared",
   363  	},
   364  }
   365  
   366  func TestReferenceScope_GetTemporaryTable(t *testing.T) {
   367  	for _, v := range referenceScopeGetTemporaryTableTests {
   368  		view, err := testTemporaryTablesReferenceScope.GetTemporaryTable(v.Path)
   369  		if err != nil {
   370  			if len(v.Error) < 1 {
   371  				t.Errorf("%s: unexpected error %q", v.Name, err)
   372  			} else if err.Error() != v.Error {
   373  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   374  			}
   375  			continue
   376  		}
   377  		if 0 < len(v.Error) {
   378  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   379  			continue
   380  		}
   381  		if !reflect.DeepEqual(view, v.Result) {
   382  			t.Errorf("%s: view = %v, want %v", v.Name, view, v.Result)
   383  		}
   384  	}
   385  }
   386  
   387  var referenceScopeGetTemporaryTableWithInternalIdTests = []struct {
   388  	Name   string
   389  	Path   parser.Identifier
   390  	Result *View
   391  	Error  string
   392  }{
   393  	{
   394  		Name: "ReferenceScope GetTemporaryTableWithInternalId",
   395  		Path: parser.Identifier{Literal: "temptable2"},
   396  		Result: &View{
   397  			Header: NewHeaderWithId("temptable2", []string{"column1", "column2"}),
   398  			RecordSet: []Record{
   399  				NewRecordWithId(0, []value.Primary{
   400  					value.NewString("1"),
   401  					value.NewString("str1"),
   402  				}),
   403  				NewRecordWithId(1, []value.Primary{
   404  					value.NewString("2"),
   405  					value.NewString("str2"),
   406  				}),
   407  			},
   408  			FileInfo: &FileInfo{
   409  				Path:      "temptable2",
   410  				Delimiter: ',',
   411  				ViewType:  ViewTypeTemporaryTable,
   412  			},
   413  		},
   414  	},
   415  	{
   416  		Name:  "ReferenceScope GetTemporaryTableWithInternalId Not Loaded Error",
   417  		Path:  parser.Identifier{Literal: "/path/to/table9.csv"},
   418  		Error: "view /path/to/table9.csv is undeclared",
   419  	},
   420  }
   421  
   422  func TestTemporaryViewScopes_GetWithInternalId(t *testing.T) {
   423  	for _, v := range referenceScopeGetTemporaryTableWithInternalIdTests {
   424  		view, err := testTemporaryTablesReferenceScope.GetTemporaryTableWithInternalId(context.Background(), v.Path, TestTx.Flags)
   425  		if err != nil {
   426  			if len(v.Error) < 1 {
   427  				t.Errorf("%s: unexpected error %q", v.Name, err)
   428  			} else if err.Error() != v.Error {
   429  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   430  			}
   431  			continue
   432  		}
   433  		if 0 < len(v.Error) {
   434  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   435  			continue
   436  		}
   437  		if !reflect.DeepEqual(view, v.Result) {
   438  			t.Errorf("%s: view = %v, want %v", v.Name, view, v.Result)
   439  		}
   440  	}
   441  }
   442  
   443  var referenceScopeSetTemporaryTableTests = []struct {
   444  	Name    string
   445  	SetView *View
   446  	Result  *ReferenceScope
   447  }{
   448  	{
   449  		Name: "ReferenceScope SetTemporaryTable",
   450  		SetView: &View{
   451  			Header: NewHeader("tempview3", []string{"column1", "column2"}),
   452  			RecordSet: []Record{
   453  				NewRecord([]value.Primary{
   454  					value.NewString("1"),
   455  					value.NewString("str1"),
   456  				}),
   457  				NewRecord([]value.Primary{
   458  					value.NewString("2"),
   459  					value.NewString("str2"),
   460  				}),
   461  			},
   462  			FileInfo: &FileInfo{
   463  				Path:      "tempview3",
   464  				Delimiter: ',',
   465  				ViewType:  ViewTypeTemporaryTable,
   466  			},
   467  		},
   468  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
   469  			{
   470  				scopeNameTempTables: {
   471  					"TEMPTABLE1": &View{
   472  						Header: NewHeader("temptable1", []string{"column1", "column2"}),
   473  						RecordSet: []Record{
   474  							NewRecord([]value.Primary{
   475  								value.NewString("1"),
   476  								value.NewString("str1"),
   477  							}),
   478  							NewRecord([]value.Primary{
   479  								value.NewString("2"),
   480  								value.NewString("str2"),
   481  							}),
   482  						},
   483  						FileInfo: &FileInfo{
   484  							Path:      "temptable1",
   485  							Delimiter: ',',
   486  							ViewType:  ViewTypeTemporaryTable,
   487  						},
   488  					},
   489  					"TEMPTABLE3": &View{
   490  						Header: NewHeader("tempview3", []string{"column1", "column2"}),
   491  						RecordSet: []Record{
   492  							NewRecord([]value.Primary{
   493  								value.NewString("1"),
   494  								value.NewString("str1"),
   495  							}),
   496  							NewRecord([]value.Primary{
   497  								value.NewString("2"),
   498  								value.NewString("str2"),
   499  							}),
   500  						},
   501  						FileInfo: &FileInfo{
   502  							Path:      "tempview3",
   503  							Delimiter: ',',
   504  							ViewType:  ViewTypeTemporaryTable,
   505  						},
   506  					},
   507  				},
   508  			},
   509  			{
   510  				scopeNameTempTables: {
   511  					"TEMPTABLE2": &View{
   512  						Header: NewHeader("temptable2", []string{"column1", "column2"}),
   513  						RecordSet: []Record{
   514  							NewRecord([]value.Primary{
   515  								value.NewString("1"),
   516  								value.NewString("str1"),
   517  							}),
   518  							NewRecord([]value.Primary{
   519  								value.NewString("2"),
   520  								value.NewString("str2"),
   521  							}),
   522  						},
   523  						FileInfo: &FileInfo{
   524  							Path:      "temptable2",
   525  							Delimiter: ',',
   526  							ViewType:  ViewTypeTemporaryTable,
   527  						},
   528  					},
   529  				},
   530  			},
   531  		}, nil, time.Time{}, nil),
   532  	},
   533  }
   534  
   535  func TestReferenceScope_SetTemporaryTable(t *testing.T) {
   536  	for _, v := range referenceScopeSetTemporaryTableTests {
   537  		testTemporaryTablesReferenceScope.SetTemporaryTable(v.SetView)
   538  		if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) {
   539  			t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks)
   540  		}
   541  	}
   542  }
   543  
   544  var referenceScopeReplaceTemporaryTableTests = []struct {
   545  	Name    string
   546  	SetView *View
   547  	Result  *ReferenceScope
   548  	Error   string
   549  }{
   550  	{
   551  		Name: "ReferenceScope ReplaceTemporaryTable",
   552  		SetView: &View{
   553  			Header: NewHeader("temptable2", []string{"column1", "column2"}),
   554  			RecordSet: []Record{
   555  				NewRecord([]value.Primary{
   556  					value.NewString("1"),
   557  					value.NewString("updated"),
   558  				}),
   559  				NewRecord([]value.Primary{
   560  					value.NewString("2"),
   561  					value.NewString("updated"),
   562  				}),
   563  			},
   564  			FileInfo: &FileInfo{
   565  				Path:      "temptable2",
   566  				Delimiter: ',',
   567  				ViewType:  ViewTypeTemporaryTable,
   568  			},
   569  		},
   570  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
   571  			{
   572  				scopeNameTempTables: {
   573  					"TEMPTABLE1": &View{
   574  						Header: NewHeader("temptable1", []string{"column1", "column2"}),
   575  						RecordSet: []Record{
   576  							NewRecord([]value.Primary{
   577  								value.NewString("1"),
   578  								value.NewString("str1"),
   579  							}),
   580  							NewRecord([]value.Primary{
   581  								value.NewString("2"),
   582  								value.NewString("str2"),
   583  							}),
   584  						},
   585  						FileInfo: &FileInfo{
   586  							Path:      "temptable1",
   587  							Delimiter: ',',
   588  							ViewType:  ViewTypeTemporaryTable,
   589  						},
   590  					},
   591  					"TEMPTABLE3": &View{
   592  						Header: NewHeader("tempview3", []string{"column1", "column2"}),
   593  						RecordSet: []Record{
   594  							NewRecord([]value.Primary{
   595  								value.NewString("1"),
   596  								value.NewString("str1"),
   597  							}),
   598  							NewRecord([]value.Primary{
   599  								value.NewString("2"),
   600  								value.NewString("str2"),
   601  							}),
   602  						},
   603  						FileInfo: &FileInfo{
   604  							Path:      "tempview3",
   605  							Delimiter: ',',
   606  							ViewType:  ViewTypeTemporaryTable,
   607  						},
   608  					},
   609  				},
   610  			},
   611  			{
   612  				scopeNameTempTables: {
   613  					"TEMPTABLE2": &View{
   614  						Header: NewHeader("temptable2", []string{"column1", "column2"}),
   615  						RecordSet: []Record{
   616  							NewRecord([]value.Primary{
   617  								value.NewString("1"),
   618  								value.NewString("updated"),
   619  							}),
   620  							NewRecord([]value.Primary{
   621  								value.NewString("2"),
   622  								value.NewString("updated"),
   623  							}),
   624  						},
   625  						FileInfo: &FileInfo{
   626  							Path:      "temptable2",
   627  							Delimiter: ',',
   628  							ViewType:  ViewTypeTemporaryTable,
   629  						},
   630  					},
   631  				},
   632  			},
   633  		}, nil, time.Time{}, nil),
   634  	},
   635  }
   636  
   637  func TestReferenceScope_ReplaceTemporaryTable(t *testing.T) {
   638  	for _, v := range referenceScopeReplaceTemporaryTableTests {
   639  		testTemporaryTablesReferenceScope.ReplaceTemporaryTable(v.SetView)
   640  		if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) {
   641  			t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks)
   642  		}
   643  	}
   644  }
   645  
   646  var referenceScopesDisposeTemporaryTableTests = []struct {
   647  	Name   string
   648  	Path   parser.Identifier
   649  	Result *ReferenceScope
   650  	Error  string
   651  }{
   652  	{
   653  		Name: "ReferenceScope DisposeTemporaryTable",
   654  		Path: parser.Identifier{Literal: "temptable1"},
   655  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
   656  			{
   657  				scopeNameTempTables: {
   658  					"TEMPTABLE3": &View{
   659  						Header: NewHeader("tempview3", []string{"column1", "column2"}),
   660  						RecordSet: []Record{
   661  							NewRecord([]value.Primary{
   662  								value.NewString("1"),
   663  								value.NewString("str1"),
   664  							}),
   665  							NewRecord([]value.Primary{
   666  								value.NewString("2"),
   667  								value.NewString("str2"),
   668  							}),
   669  						},
   670  						FileInfo: &FileInfo{
   671  							Path:      "tempview3",
   672  							Delimiter: ',',
   673  							ViewType:  ViewTypeTemporaryTable,
   674  						},
   675  					},
   676  				},
   677  			},
   678  			{
   679  				scopeNameTempTables: {
   680  					"TEMPTABLE2": &View{
   681  						Header: NewHeader("temptable2", []string{"column1", "column2"}),
   682  						RecordSet: []Record{
   683  							NewRecord([]value.Primary{
   684  								value.NewString("1"),
   685  								value.NewString("updated"),
   686  							}),
   687  							NewRecord([]value.Primary{
   688  								value.NewString("2"),
   689  								value.NewString("updated"),
   690  							}),
   691  						},
   692  						FileInfo: &FileInfo{
   693  							Path:      "temptable2",
   694  							Delimiter: ',',
   695  							ViewType:  ViewTypeTemporaryTable,
   696  						},
   697  					},
   698  				},
   699  			},
   700  		}, nil, time.Time{}, nil),
   701  	},
   702  	{
   703  		Name:  "ReferenceScope DisposeTemporaryTable Not Loaded Error",
   704  		Path:  parser.Identifier{Literal: "/path/to/table9.csv"},
   705  		Error: "view /path/to/table9.csv is undeclared",
   706  	},
   707  }
   708  
   709  func TestReferenceScope_DisposeTemporaryTable(t *testing.T) {
   710  	for _, v := range referenceScopesDisposeTemporaryTableTests {
   711  		err := testTemporaryTablesReferenceScope.DisposeTemporaryTable(v.Path)
   712  		if err != nil {
   713  			if len(v.Error) < 1 {
   714  				t.Errorf("%s: unexpected error %q", v.Name, err)
   715  			} else if err.Error() != v.Error {
   716  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   717  			}
   718  			continue
   719  		}
   720  		if 0 < len(v.Error) {
   721  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   722  			continue
   723  		}
   724  		if !BlockScopeListEqual(testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks) {
   725  			t.Errorf("%s: blocks = %v, want %v", v.Name, testTemporaryTablesReferenceScope.Blocks, v.Result.Blocks)
   726  		}
   727  	}
   728  }
   729  
   730  func TestReferenceScope_StoreTemporaryTable(t *testing.T) {
   731  	scope := GenerateReferenceScope([]map[string]map[string]interface{}{
   732  		{
   733  			scopeNameTempTables: {
   734  				"TEMPTABLE3": &View{
   735  					Header: NewHeader("tempview3", []string{"column1", "column2"}),
   736  					RecordSet: []Record{
   737  						NewRecord([]value.Primary{
   738  							value.NewString("1"),
   739  							value.NewString("str1"),
   740  						}),
   741  						NewRecord([]value.Primary{
   742  							value.NewString("2"),
   743  							value.NewString("str2"),
   744  						}),
   745  					},
   746  					FileInfo: &FileInfo{
   747  						Path:      "tempview3",
   748  						Delimiter: ',',
   749  						ViewType:  ViewTypeTemporaryTable,
   750  					},
   751  				},
   752  			},
   753  		},
   754  		{
   755  			scopeNameTempTables: {
   756  				"TEMPTABLE2": &View{
   757  					Header: NewHeader("temptable2", []string{"column1", "column2"}),
   758  					RecordSet: []Record{
   759  						NewRecord([]value.Primary{
   760  							value.NewString("1"),
   761  							value.NewString("updated"),
   762  						}),
   763  						NewRecord([]value.Primary{
   764  							value.NewString("2"),
   765  							value.NewString("updated"),
   766  						}),
   767  					},
   768  					FileInfo: &FileInfo{
   769  						Path:                  "temptable2",
   770  						Delimiter:             ',',
   771  						ViewType:              ViewTypeTemporaryTable,
   772  						restorePointHeader:    NewHeader("table2", []string{"column1", "column2"}),
   773  						restorePointRecordSet: RecordSet{},
   774  					},
   775  				},
   776  			},
   777  		},
   778  	}, nil, time.Time{}, nil)
   779  
   780  	expect := GenerateReferenceScope([]map[string]map[string]interface{}{
   781  		{
   782  			scopeNameTempTables: {
   783  				"TEMPTABLE3": &View{
   784  					Header: NewHeader("tempview3", []string{"column1", "column2"}),
   785  					RecordSet: []Record{
   786  						NewRecord([]value.Primary{
   787  							value.NewString("1"),
   788  							value.NewString("str1"),
   789  						}),
   790  						NewRecord([]value.Primary{
   791  							value.NewString("2"),
   792  							value.NewString("str2"),
   793  						}),
   794  					},
   795  					FileInfo: &FileInfo{
   796  						Path:      "tempview3",
   797  						Delimiter: ',',
   798  						ViewType:  ViewTypeTemporaryTable,
   799  					},
   800  				},
   801  			},
   802  		},
   803  		{
   804  			scopeNameTempTables: {
   805  				"TEMPTABLE2": &View{
   806  					Header: NewHeader("temptable2", []string{"column1", "column2"}),
   807  					RecordSet: []Record{
   808  						NewRecord([]value.Primary{
   809  							value.NewString("1"),
   810  							value.NewString("updated"),
   811  						}),
   812  						NewRecord([]value.Primary{
   813  							value.NewString("2"),
   814  							value.NewString("updated"),
   815  						}),
   816  					},
   817  					FileInfo: &FileInfo{
   818  						Path:               "temptable2",
   819  						Delimiter:          ',',
   820  						ViewType:           ViewTypeTemporaryTable,
   821  						restorePointHeader: NewHeader("temptable2", []string{"column1", "column2"}),
   822  						restorePointRecordSet: []Record{
   823  							NewRecord([]value.Primary{
   824  								value.NewString("1"),
   825  								value.NewString("updated"),
   826  							}),
   827  							NewRecord([]value.Primary{
   828  								value.NewString("2"),
   829  								value.NewString("updated"),
   830  							}),
   831  						},
   832  					},
   833  				},
   834  			},
   835  		},
   836  	}, nil, time.Time{}, nil)
   837  
   838  	expectOut := []string{"Commit: restore point of view \"temptable2\" is created.\n"}
   839  
   840  	UncommittedViews := map[string]*FileInfo{
   841  		"TEMPTABLE2": nil,
   842  	}
   843  
   844  	log := scope.StoreTemporaryTable(TestTx.Session, UncommittedViews)
   845  
   846  	if !BlockScopeListEqual(scope.Blocks, expect.Blocks) {
   847  		t.Errorf("Store: blocks = %v, want %v", scope.Blocks, expect.Blocks)
   848  	}
   849  
   850  	if reflect.DeepEqual(log, expectOut) {
   851  		t.Errorf("Store: log = %s, want %s", log, expectOut)
   852  	}
   853  }
   854  
   855  func TestReferenceScope_RestoreTemporaryTable(t *testing.T) {
   856  	scope := GenerateReferenceScope([]map[string]map[string]interface{}{
   857  		{
   858  			scopeNameTempTables: {
   859  				"TEMPTABLE3": &View{
   860  					Header: NewHeader("tempview3", []string{"column1", "column2"}),
   861  					RecordSet: []Record{
   862  						NewRecord([]value.Primary{
   863  							value.NewString("1"),
   864  							value.NewString("str1"),
   865  						}),
   866  						NewRecord([]value.Primary{
   867  							value.NewString("2"),
   868  							value.NewString("str2"),
   869  						}),
   870  					},
   871  					FileInfo: &FileInfo{
   872  						Path:      "tempview3",
   873  						Delimiter: ',',
   874  						ViewType:  ViewTypeTemporaryTable,
   875  					},
   876  				},
   877  			},
   878  		},
   879  		{
   880  			scopeNameTempTables: {
   881  				"TEMPTABLE2": &View{
   882  					Header: NewHeader("temptable2", []string{"column1", "column2"}),
   883  					RecordSet: []Record{
   884  						NewRecord([]value.Primary{
   885  							value.NewString("1"),
   886  							value.NewString("updated"),
   887  						}),
   888  						NewRecord([]value.Primary{
   889  							value.NewString("2"),
   890  							value.NewString("updated"),
   891  						}),
   892  					},
   893  					FileInfo: &FileInfo{
   894  						Path:               "temptable2",
   895  						Delimiter:          ',',
   896  						ViewType:           ViewTypeTemporaryTable,
   897  						restorePointHeader: NewHeader("temptable2", []string{"column1", "column2"}),
   898  						restorePointRecordSet: []Record{
   899  							NewRecord([]value.Primary{
   900  								value.NewString("1"),
   901  								value.NewString("str1"),
   902  							}),
   903  							NewRecord([]value.Primary{
   904  								value.NewString("2"),
   905  								value.NewString("str2"),
   906  							}),
   907  						},
   908  					},
   909  				},
   910  			},
   911  		},
   912  	}, nil, time.Time{}, nil)
   913  
   914  	expect := GenerateReferenceScope([]map[string]map[string]interface{}{
   915  		{
   916  			scopeNameTempTables: {
   917  				"TEMPTABLE3": &View{
   918  					Header: NewHeader("tempview3", []string{"column1", "column2"}),
   919  					RecordSet: []Record{
   920  						NewRecord([]value.Primary{
   921  							value.NewString("1"),
   922  							value.NewString("str1"),
   923  						}),
   924  						NewRecord([]value.Primary{
   925  							value.NewString("2"),
   926  							value.NewString("str2"),
   927  						}),
   928  					},
   929  					FileInfo: &FileInfo{
   930  						Path:      "tempview3",
   931  						Delimiter: ',',
   932  						ViewType:  ViewTypeTemporaryTable,
   933  					},
   934  				},
   935  			},
   936  		},
   937  		{
   938  			scopeNameTempTables: {
   939  				"TEMPTABLE2": &View{
   940  					Header: NewHeader("temptable2", []string{"column1", "column2"}),
   941  					RecordSet: []Record{
   942  						NewRecord([]value.Primary{
   943  							value.NewString("1"),
   944  							value.NewString("str1"),
   945  						}),
   946  						NewRecord([]value.Primary{
   947  							value.NewString("2"),
   948  							value.NewString("str2"),
   949  						}),
   950  					},
   951  					FileInfo: &FileInfo{
   952  						Path:               "temptable2",
   953  						Delimiter:          ',',
   954  						ViewType:           ViewTypeTemporaryTable,
   955  						restorePointHeader: NewHeader("temptable2", []string{"column1", "column2"}),
   956  						restorePointRecordSet: []Record{
   957  							NewRecord([]value.Primary{
   958  								value.NewString("1"),
   959  								value.NewString("str1"),
   960  							}),
   961  							NewRecord([]value.Primary{
   962  								value.NewString("2"),
   963  								value.NewString("str2"),
   964  							}),
   965  						},
   966  					},
   967  				},
   968  			},
   969  		},
   970  	}, nil, time.Time{}, nil)
   971  	expectOut := []string{"Rollback: view \"tempview2\" is restored.\n"}
   972  
   973  	UncommittedViews := map[string]*FileInfo{
   974  		"TEMPTABLE2": nil,
   975  	}
   976  
   977  	log := scope.RestoreTemporaryTable(UncommittedViews)
   978  
   979  	if !BlockScopeListEqual(scope.Blocks, expect.Blocks) {
   980  		t.Errorf("Restore: blocks = %v, want %v", scope.Blocks, expect.Blocks)
   981  	}
   982  
   983  	if reflect.DeepEqual(log, expectOut) {
   984  		t.Errorf("Restore: log = %s, want %s", log, expectOut)
   985  	}
   986  }
   987  
   988  var referenceScopeDisposeCursorTests = []struct {
   989  	Name    string
   990  	CurName parser.Identifier
   991  	Result  *ReferenceScope
   992  	Error   string
   993  }{
   994  	{
   995  		Name:    "ReferenceScope DisposeCursor",
   996  		CurName: parser.Identifier{Literal: "cur"},
   997  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
   998  			{
   999  				scopeNameCursors: {
  1000  					"PCUR": &Cursor{
  1001  						view: &View{
  1002  							Header: NewHeader("", []string{"c1"}),
  1003  							RecordSet: RecordSet{
  1004  								NewRecord([]value.Primary{value.NewInteger(1)}),
  1005  								NewRecord([]value.Primary{value.NewInteger(2)}),
  1006  							},
  1007  						},
  1008  						index:    -1,
  1009  						isPseudo: true,
  1010  						mtx:      &sync.Mutex{},
  1011  					},
  1012  				},
  1013  			},
  1014  		}, nil, time.Time{}, nil),
  1015  	},
  1016  	{
  1017  		Name:    "ReferenceScope DisposeCursor Pseudo Cursor Error",
  1018  		CurName: parser.Identifier{Literal: "pcur"},
  1019  		Error:   "cursor pcur is a pseudo cursor",
  1020  	},
  1021  	{
  1022  		Name:    "ReferenceScope DisposeCursor Undeclared Error",
  1023  		CurName: parser.Identifier{Literal: "notexist"},
  1024  		Error:   "cursor notexist is undeclared",
  1025  	},
  1026  }
  1027  
  1028  func TestReferenceScope_DisposeCursor(t *testing.T) {
  1029  	scope := GenerateReferenceScope([]map[string]map[string]interface{}{
  1030  		{
  1031  			scopeNameCursors: {
  1032  				"PCUR": &Cursor{
  1033  					view: &View{
  1034  						Header: NewHeader("", []string{"c1"}),
  1035  						RecordSet: RecordSet{
  1036  							NewRecord([]value.Primary{value.NewInteger(1)}),
  1037  							NewRecord([]value.Primary{value.NewInteger(2)}),
  1038  						},
  1039  					},
  1040  					index:    -1,
  1041  					isPseudo: true,
  1042  					mtx:      &sync.Mutex{},
  1043  				},
  1044  				"CUR": &Cursor{
  1045  					query: selectQueryForCursorTest,
  1046  					mtx:   &sync.Mutex{},
  1047  				},
  1048  			},
  1049  		},
  1050  	}, nil, time.Time{}, nil)
  1051  
  1052  	for _, v := range referenceScopeDisposeCursorTests {
  1053  		err := scope.DisposeCursor(v.CurName)
  1054  		if err != nil {
  1055  			if len(v.Error) < 1 {
  1056  				t.Errorf("%s: unexpected error %q", v.Name, err)
  1057  			} else if err.Error() != v.Error {
  1058  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  1059  			}
  1060  			continue
  1061  		}
  1062  		if 0 < len(v.Error) {
  1063  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  1064  			continue
  1065  		}
  1066  		if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) {
  1067  			t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks)
  1068  		}
  1069  	}
  1070  }
  1071  
  1072  var referenceScopeOpenCursorTests = []struct {
  1073  	Name      string
  1074  	CurName   parser.Identifier
  1075  	CurValues []parser.ReplaceValue
  1076  	Result    *ReferenceScope
  1077  	Error     string
  1078  }{
  1079  	{
  1080  		Name:    "ReferenceScope OpenCursor",
  1081  		CurName: parser.Identifier{Literal: "cur"},
  1082  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
  1083  			{
  1084  				scopeNameCursors: {
  1085  					"PCUR": &Cursor{
  1086  						view: &View{
  1087  							Header: NewHeader("", []string{"c1"}),
  1088  							RecordSet: RecordSet{
  1089  								NewRecord([]value.Primary{value.NewInteger(1)}),
  1090  								NewRecord([]value.Primary{value.NewInteger(2)}),
  1091  							},
  1092  						},
  1093  						index:    -1,
  1094  						isPseudo: true,
  1095  						mtx:      &sync.Mutex{},
  1096  					},
  1097  					"CUR": &Cursor{
  1098  						query: selectQueryForCursorTest,
  1099  						view: &View{
  1100  							Header: NewHeader("table1", []string{"column1", "column2"}),
  1101  							RecordSet: []Record{
  1102  								NewRecord([]value.Primary{
  1103  									value.NewString("1"),
  1104  									value.NewString("str1"),
  1105  								}),
  1106  								NewRecord([]value.Primary{
  1107  									value.NewString("2"),
  1108  									value.NewString("str2"),
  1109  								}),
  1110  								NewRecord([]value.Primary{
  1111  									value.NewString("3"),
  1112  									value.NewString("str3"),
  1113  								}),
  1114  							},
  1115  							FileInfo: &FileInfo{
  1116  								Path:      GetTestFilePath("table1.csv"),
  1117  								Delimiter: ',',
  1118  								NoHeader:  false,
  1119  								Encoding:  text.UTF8,
  1120  								LineBreak: text.LF,
  1121  							},
  1122  						},
  1123  						index: -1,
  1124  						mtx:   &sync.Mutex{},
  1125  					},
  1126  				},
  1127  			},
  1128  		}, nil, time.Time{}, nil),
  1129  	},
  1130  	{
  1131  		Name:    "ReferenceScope OpenCursor Undeclared Error",
  1132  		CurName: parser.Identifier{Literal: "notexist"},
  1133  		Error:   "cursor notexist is undeclared",
  1134  	},
  1135  	{
  1136  		Name:    "ReferenceScope OpenCursor Open Error",
  1137  		CurName: parser.Identifier{Literal: "cur"},
  1138  		Error:   "cursor cur is already open",
  1139  	},
  1140  	{
  1141  		Name:    "ReferenceScope OpenCursor Pseudo Cursor Error",
  1142  		CurName: parser.Identifier{Literal: "pcur"},
  1143  		Error:   "cursor pcur is a pseudo cursor",
  1144  	},
  1145  }
  1146  
  1147  func TestReferenceScope_OpenCursor(t *testing.T) {
  1148  	defer func() {
  1149  		_ = TestTx.CachedViews.Clean(TestTx.FileContainer)
  1150  		initFlag(TestTx.Flags)
  1151  	}()
  1152  
  1153  	TestTx.Flags.Repository = TestDir
  1154  
  1155  	scope := GenerateReferenceScope([]map[string]map[string]interface{}{
  1156  		{
  1157  			scopeNameCursors: {
  1158  				"PCUR": &Cursor{
  1159  					view: &View{
  1160  						Header: NewHeader("", []string{"c1"}),
  1161  						RecordSet: RecordSet{
  1162  							NewRecord([]value.Primary{value.NewInteger(1)}),
  1163  							NewRecord([]value.Primary{value.NewInteger(2)}),
  1164  						},
  1165  					},
  1166  					index:    -1,
  1167  					isPseudo: true,
  1168  					mtx:      &sync.Mutex{},
  1169  				},
  1170  				"CUR": &Cursor{
  1171  					query: selectQueryForCursorTest,
  1172  					mtx:   &sync.Mutex{},
  1173  				},
  1174  			},
  1175  		},
  1176  	}, nil, time.Time{}, nil)
  1177  
  1178  	for _, v := range referenceScopeOpenCursorTests {
  1179  		_ = TestTx.CachedViews.Clean(TestTx.FileContainer)
  1180  
  1181  		err := scope.OpenCursor(context.Background(), v.CurName, v.CurValues)
  1182  		if err != nil {
  1183  			if len(v.Error) < 1 {
  1184  				t.Errorf("%s: unexpected error %q", v.Name, err)
  1185  			} else if err.Error() != v.Error {
  1186  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  1187  			}
  1188  			continue
  1189  		}
  1190  		if 0 < len(v.Error) {
  1191  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  1192  			continue
  1193  		}
  1194  		if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) {
  1195  			t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks)
  1196  		}
  1197  	}
  1198  }
  1199  
  1200  var referenceScopeCloseCursorTests = []struct {
  1201  	Name    string
  1202  	CurName parser.Identifier
  1203  	Result  *ReferenceScope
  1204  	Error   string
  1205  }{
  1206  	{
  1207  		Name:    "ReferenceScope CloseCursor",
  1208  		CurName: parser.Identifier{Literal: "cur"},
  1209  		Result: GenerateReferenceScope([]map[string]map[string]interface{}{
  1210  			{
  1211  				scopeNameCursors: {
  1212  					"PCUR": &Cursor{
  1213  						view: &View{
  1214  							Header: NewHeader("", []string{"c1"}),
  1215  							RecordSet: RecordSet{
  1216  								NewRecord([]value.Primary{value.NewInteger(1)}),
  1217  								NewRecord([]value.Primary{value.NewInteger(2)}),
  1218  							},
  1219  						},
  1220  						index:    -1,
  1221  						isPseudo: true,
  1222  						mtx:      &sync.Mutex{},
  1223  					},
  1224  					"CUR": &Cursor{
  1225  						query: selectQueryForCursorTest,
  1226  						mtx:   &sync.Mutex{},
  1227  					},
  1228  				},
  1229  			},
  1230  		}, nil, time.Time{}, nil),
  1231  	},
  1232  	{
  1233  		Name:    "ReferenceScope CloseCursor Pseudo Cursor Error",
  1234  		CurName: parser.Identifier{Literal: "pcur"},
  1235  		Error:   "cursor pcur is a pseudo cursor",
  1236  	},
  1237  	{
  1238  		Name:    "ReferenceScope CloseCursor Undeclared Error",
  1239  		CurName: parser.Identifier{Literal: "notexist"},
  1240  		Error:   "cursor notexist is undeclared",
  1241  	},
  1242  }
  1243  
  1244  func TestReferenceScope_CloseCursor(t *testing.T) {
  1245  	defer func() {
  1246  		_ = TestTx.CachedViews.Clean(TestTx.FileContainer)
  1247  		initFlag(TestTx.Flags)
  1248  	}()
  1249  
  1250  	TestTx.Flags.Repository = TestDir
  1251  
  1252  	scope := GenerateReferenceScope([]map[string]map[string]interface{}{
  1253  		{
  1254  			scopeNameCursors: {
  1255  				"PCUR": &Cursor{
  1256  					view: &View{
  1257  						Header: NewHeader("", []string{"c1"}),
  1258  						RecordSet: RecordSet{
  1259  							NewRecord([]value.Primary{value.NewInteger(1)}),
  1260  							NewRecord([]value.Primary{value.NewInteger(2)}),
  1261  						},
  1262  					},
  1263  					index:    -1,
  1264  					isPseudo: true,
  1265  					mtx:      &sync.Mutex{},
  1266  				},
  1267  				"CUR": &Cursor{
  1268  					query: selectQueryForCursorTest,
  1269  					view: &View{
  1270  						Header: NewHeader("table1", []string{"column1", "column2"}),
  1271  						RecordSet: []Record{
  1272  							NewRecord([]value.Primary{
  1273  								value.NewString("1"),
  1274  								value.NewString("str1"),
  1275  							}),
  1276  							NewRecord([]value.Primary{
  1277  								value.NewString("2"),
  1278  								value.NewString("str2"),
  1279  							}),
  1280  							NewRecord([]value.Primary{
  1281  								value.NewString("3"),
  1282  								value.NewString("str3"),
  1283  							}),
  1284  						},
  1285  						FileInfo: &FileInfo{
  1286  							Path:      GetTestFilePath("table1.csv"),
  1287  							Delimiter: ',',
  1288  							NoHeader:  false,
  1289  							Encoding:  text.UTF8,
  1290  							LineBreak: text.LF,
  1291  						},
  1292  					},
  1293  					index: -1,
  1294  					mtx:   &sync.Mutex{},
  1295  				},
  1296  			},
  1297  		},
  1298  	}, nil, time.Time{}, nil)
  1299  
  1300  	for _, v := range referenceScopeCloseCursorTests {
  1301  		err := scope.CloseCursor(v.CurName)
  1302  		if err != nil {
  1303  			if len(v.Error) < 1 {
  1304  				t.Errorf("%s: unexpected error %q", v.Name, err)
  1305  			} else if err.Error() != v.Error {
  1306  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  1307  			}
  1308  			continue
  1309  		}
  1310  		if 0 < len(v.Error) {
  1311  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  1312  			continue
  1313  		}
  1314  		if !BlockScopeListEqual(scope.Blocks, v.Result.Blocks) {
  1315  			t.Errorf("%s: blocks = %v, want %v", v.Name, scope.Blocks, v.Result.Blocks)
  1316  		}
  1317  	}
  1318  }