github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/mvdata/data_loc_test.go (about) 1 // Copyright 2019 Dolthub, Inc. 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 mvdata 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "reflect" 22 "strings" 23 "testing" 24 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 28 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 29 "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" 30 "github.com/dolthub/dolt/go/libraries/doltcore/row" 31 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 32 "github.com/dolthub/dolt/go/libraries/doltcore/table" 33 "github.com/dolthub/dolt/go/libraries/doltcore/table/editor" 34 "github.com/dolthub/dolt/go/libraries/doltcore/table/typed/json" 35 "github.com/dolthub/dolt/go/libraries/doltcore/table/untyped/csv" 36 "github.com/dolthub/dolt/go/libraries/utils/filesys" 37 "github.com/dolthub/dolt/go/store/types" 38 ) 39 40 const ( 41 testTableName = "test_table" 42 testSchemaFileName = "schema.sql" 43 testSchema = ` 44 CREATE TABLE test_table ( 45 a VARCHAR(120) COMMENT 'tag:0', 46 b VARCHAR(120) COMMENT 'tag:1', 47 PRIMARY KEY(a) 48 );` 49 ) 50 51 var rowMap = []map[string]interface{}{ 52 {"a": []string{"a", "b", "c"}}, 53 {"b": []string{"1", "2", "3"}}, 54 } 55 56 func createRootAndFS() (*doltdb.DoltDB, doltdb.RootValue, filesys.Filesys) { 57 58 testHomeDir := "/user/bheni" 59 workingDir := "/user/bheni/datasets/states" 60 initialDirs := []string{testHomeDir, workingDir} 61 fs := filesys.NewInMemFS(initialDirs, nil, workingDir) 62 fs.WriteFile(testSchemaFileName, []byte(testSchema), os.ModePerm) 63 ddb, _ := doltdb.LoadDoltDB(context.Background(), types.Format_Default, doltdb.InMemDoltDB, filesys.LocalFS) 64 ddb.WriteEmptyRepo(context.Background(), "master", "billy bob", "bigbillieb@fake.horse") 65 66 cs, _ := doltdb.NewCommitSpec("master") 67 optCmt, _ := ddb.Resolve(context.Background(), cs, nil) 68 commit, _ := optCmt.ToCommit() 69 root, err := commit.GetRootValue(context.Background()) 70 71 if err != nil { 72 panic(err) 73 } 74 75 return ddb, root, fs 76 } 77 78 func TestBasics(t *testing.T) { 79 tests := []struct { 80 dl DataLocation 81 expectedStr string 82 expectedIsFileType bool 83 }{ 84 {NewDataLocation("", ".csv"), "stream", false}, 85 {NewDataLocation("file.csv", ""), CsvFile.ReadableStr() + ":file.csv", true}, 86 {NewDataLocation("file.psv", ""), PsvFile.ReadableStr() + ":file.psv", true}, 87 {NewDataLocation("file.json", ""), JsonFile.ReadableStr() + ":file.json", true}, 88 //{NewDataLocation("file.nbf", ""), NbfFile, "file.nbf", true}, 89 } 90 91 for _, test := range tests { 92 t.Run(test.dl.String(), func(t *testing.T) { 93 assert.Equal(t, test.expectedStr, test.dl.String()) 94 95 _, isFileType := test.dl.(FileDataLocation) 96 assert.Equal(t, test.expectedIsFileType, isFileType) 97 }) 98 } 99 } 100 101 var fakeFields = schema.NewColCollection( 102 schema.NewColumn("a", 0, types.StringKind, true, schema.NotNullConstraint{}), 103 schema.NewColumn("b", 1, types.StringKind, false), 104 ) 105 106 func mustRow(r row.Row, err error) row.Row { 107 if err != nil { 108 panic(err) 109 } 110 111 return r 112 } 113 114 var fakeSchema schema.Schema 115 var imt *table.InMemTable 116 var imtRows []row.Row 117 118 func init() { 119 fakeSchema = schema.MustSchemaFromCols(fakeFields) 120 121 imtRows = []row.Row{ 122 mustRow(row.New(types.Format_Default, fakeSchema, row.TaggedValues{0: types.String("a"), 1: types.String("1")})), 123 mustRow(row.New(types.Format_Default, fakeSchema, row.TaggedValues{0: types.String("b"), 1: types.String("2")})), 124 mustRow(row.New(types.Format_Default, fakeSchema, row.TaggedValues{0: types.String("c"), 1: types.String("3")})), 125 } 126 127 imt = table.NewInMemTableWithData(fakeSchema, imtRows) 128 } 129 130 func TestExists(t *testing.T) { 131 testLocations := []DataLocation{ 132 NewDataLocation("file.csv", ""), 133 NewDataLocation("file.psv", ""), 134 NewDataLocation("file.json", ""), 135 //NewDataLocation("file.nbf", ""), 136 } 137 138 ddb, root, fs := createRootAndFS() 139 defer ddb.Close() 140 141 for _, loc := range testLocations { 142 t.Run(loc.String(), func(t *testing.T) { 143 if exists, err := loc.Exists(context.Background(), root, fs); err != nil { 144 t.Error(err) 145 } else if exists { 146 t.Error("Shouldn't exist before creation") 147 } 148 149 if fileVal, isFile := loc.(FileDataLocation); isFile { 150 err := fs.WriteFile(fileVal.Path, []byte("test"), os.ModePerm) 151 assert.NoError(t, err) 152 } 153 154 if exists, err := loc.Exists(context.Background(), root, fs); err != nil { 155 t.Error(err) 156 } else if !exists { 157 t.Error("Should already exist after creation") 158 } 159 }) 160 } 161 } 162 163 type testDataMoverOptions struct{} 164 165 func (t testDataMoverOptions) IsBatched() bool { 166 return false 167 } 168 169 func (t testDataMoverOptions) IsAutocommitOff() bool { 170 return false 171 } 172 173 func (t testDataMoverOptions) WritesToTable() bool { 174 return true 175 } 176 177 func (t testDataMoverOptions) SrcName() string { 178 return "" 179 } 180 181 func (t testDataMoverOptions) DestName() string { 182 return testTableName 183 } 184 185 func TestCreateRdWr(t *testing.T) { 186 tests := []struct { 187 dl DataLocation 188 expectedRdT reflect.Type 189 expectedWrT reflect.Type 190 }{ 191 {NewDataLocation("file.csv", ""), reflect.TypeOf((*csv.CSVReader)(nil)).Elem(), reflect.TypeOf((*csv.CSVWriter)(nil)).Elem()}, 192 {NewDataLocation("file.psv", ""), reflect.TypeOf((*csv.CSVReader)(nil)).Elem(), reflect.TypeOf((*csv.CSVWriter)(nil)).Elem()}, 193 {NewDataLocation("file.json", ""), reflect.TypeOf((*json.JSONReader)(nil)).Elem(), reflect.TypeOf((*json.RowWriter)(nil)).Elem()}, 194 //{NewDataLocation("file.nbf", ""), reflect.TypeOf((*nbf.NBFReader)(nil)).Elem(), reflect.TypeOf((*nbf.NBFWriter)(nil)).Elem()}, 195 } 196 197 dEnv := dtestutils.CreateTestEnv() 198 defer dEnv.DoltDB.Close() 199 root, err := dEnv.WorkingRoot(context.Background()) 200 require.NoError(t, err) 201 dEnv.FS.WriteFile(testSchemaFileName, []byte(testSchema), os.ModePerm) 202 203 mvOpts := &testDataMoverOptions{} 204 205 for idx, test := range tests { 206 fmt.Println(idx) 207 208 loc := test.dl 209 210 tmpDir, tdErr := dEnv.TempTableFilesDir() 211 if tdErr != nil { 212 t.Fatal("Unexpected error accessing .dolt directory.", tdErr) 213 } 214 opts := editor.Options{Deaf: dEnv.DbEaFactory(), Tempdir: tmpDir} 215 216 filePath, fpErr := dEnv.FS.Abs(strings.Split(loc.String(), ":")[1]) 217 if fpErr != nil { 218 t.Fatal("Unexpected error getting filepath", fpErr) 219 } 220 221 writer, wrErr := dEnv.FS.OpenForWrite(filePath, os.ModePerm) 222 if wrErr != nil { 223 t.Fatal("Unexpected error opening file for writer.", wrErr) 224 } 225 226 wr, wErr := loc.NewCreatingWriter(context.Background(), mvOpts, root, fakeSchema, opts, writer) 227 if wErr != nil { 228 t.Fatal("Unexpected error creating writer.", wErr) 229 } 230 231 actualWrT := reflect.TypeOf(wr).Elem() 232 if actualWrT != test.expectedWrT { 233 t.Fatal("Unexpected writer type. Expected:", test.expectedWrT.Name(), "actual:", actualWrT.Name()) 234 } 235 236 inMemRd := table.NewInMemTableReader(imt) 237 _, numBad, pipeErr := table.PipeRows(context.Background(), inMemRd, wr, false) 238 wr.Close(context.Background()) 239 240 if numBad != 0 || pipeErr != nil { 241 t.Fatal("Failed to write data. bad:", numBad, err) 242 } 243 244 rd, _, err := loc.NewReader(context.Background(), dEnv, JSONOptions{TableName: testTableName, SchFile: testSchemaFileName}) 245 246 if err != nil { 247 t.Fatal("Unexpected error creating reader", err) 248 } 249 250 actualRdT := reflect.TypeOf(rd).Elem() 251 if actualRdT != test.expectedRdT { 252 t.Error("Unexpected reader type. Expected:", test.expectedRdT.Name(), "actual:", actualRdT.Name()) 253 } 254 255 rd.Close(context.Background()) 256 } 257 }