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  }