github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/copy_file_upload_test.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package sql 12 13 import ( 14 "bytes" 15 "context" 16 gosql "database/sql" 17 "io" 18 "io/ioutil" 19 "net/url" 20 "os" 21 "path/filepath" 22 "testing" 23 24 "github.com/cockroachdb/cockroach/pkg/sql/tests" 25 "github.com/cockroachdb/cockroach/pkg/testutils" 26 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" 27 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 28 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 29 "github.com/stretchr/testify/require" 30 ) 31 32 const filename = "/test/test_file_upload.csv" 33 34 func writeFile(t *testing.T, testSendFile string, fileContent []byte) { 35 err := os.MkdirAll(filepath.Dir(testSendFile), 0755) 36 if err != nil { 37 t.Fatal(err) 38 } 39 err = ioutil.WriteFile(testSendFile, fileContent, 0644) 40 if err != nil { 41 t.Fatal(err) 42 } 43 } 44 45 func runCopyFile(t *testing.T, db *gosql.DB, testSendFile string) error { 46 // Make sure we can open this file first 47 reader, err := os.Open(testSendFile) 48 if err != nil { 49 return err 50 } 51 52 txn, err := db.Begin() 53 if err != nil { 54 t.Fatal(err) 55 } 56 defer func() { 57 if newErr := txn.Commit(); err == nil && newErr != nil { 58 t.Fatal(newErr) 59 } 60 }() 61 62 stmt, err := txn.Prepare(CopyInFileStmt(filename, crdbInternalName, fileUploadTable)) 63 if err != nil { 64 return err 65 } 66 67 for { 68 send := make([]byte, 1024) 69 n, err := reader.Read(send) 70 if err == io.EOF { 71 break 72 } 73 if err != nil { 74 t.Fatal(err) 75 } 76 _, err = stmt.Exec(string(send[:n])) 77 if err != nil { 78 t.Fatal(err) 79 } 80 } 81 82 err = stmt.Close() 83 if err != nil { 84 t.Fatal(err) 85 } 86 return nil 87 } 88 89 func TestFileUpload(t *testing.T) { 90 defer leaktest.AfterTest(t)() 91 92 params, _ := tests.CreateTestServerParams() 93 localExternalDir, cleanup := testutils.TempDir(t) 94 defer cleanup() 95 params.ExternalIODir = localExternalDir 96 97 s, db, _ := serverutils.StartServer(t, params) 98 defer s.Stopper().Stop(context.Background()) 99 100 testFileDir, cleanup2 := testutils.TempDir(t) 101 defer cleanup2() 102 testSendFile := filepath.Join(testFileDir, filename) 103 fileContent := []byte("hello \n blah 1@#% some data hello \n @#%^&&*") 104 writeFile(t, testSendFile, fileContent) 105 106 err := runCopyFile(t, db, testSendFile) 107 if err != nil { 108 t.Fatal(err) 109 } 110 111 content, err := ioutil.ReadFile(filepath.Join(localExternalDir, filename)) 112 if err != nil { 113 t.Fatal(err) 114 } 115 if !bytes.Equal(fileContent, content) { 116 t.Fatalf("content not the same. expected: %s got: %s", fileContent, content) 117 } 118 } 119 120 func TestUploadEmptyFile(t *testing.T) { 121 defer leaktest.AfterTest(t)() 122 123 params, _ := tests.CreateTestServerParams() 124 localExternalDir, cleanup := testutils.TempDir(t) 125 defer cleanup() 126 params.ExternalIODir = localExternalDir 127 s, db, _ := serverutils.StartServer(t, params) 128 defer s.Stopper().Stop(context.Background()) 129 130 testFileDir, cleanup2 := testutils.TempDir(t) 131 defer cleanup2() 132 testSendFile := filepath.Join(testFileDir, filename) 133 fileContent := []byte("") 134 writeFile(t, testSendFile, fileContent) 135 136 err := runCopyFile(t, db, testSendFile) 137 if err != nil { 138 t.Fatal(err) 139 } 140 141 content, err := ioutil.ReadFile(filepath.Join(localExternalDir, filename)) 142 if err != nil { 143 t.Fatal(err) 144 } 145 if !bytes.Equal(fileContent, content) { 146 t.Fatalf("content not the same. expected: %s got: %s", fileContent, content) 147 } 148 } 149 150 func TestFileNotExist(t *testing.T) { 151 defer leaktest.AfterTest(t)() 152 153 params, _ := tests.CreateTestServerParams() 154 localExternalDir, cleanup := testutils.TempDir(t) 155 defer cleanup() 156 params.ExternalIODir = localExternalDir 157 s, db, _ := serverutils.StartServer(t, params) 158 defer s.Stopper().Stop(context.Background()) 159 160 err := runCopyFile(t, db, filepath.Join(localExternalDir, filename)) 161 expectedErr := "no such file" 162 if !testutils.IsError(err, expectedErr) { 163 t.Fatalf(`expected error: %s, got: %s`, expectedErr, err) 164 } 165 } 166 167 func TestFileExist(t *testing.T) { 168 defer leaktest.AfterTest(t)() 169 170 params, _ := tests.CreateTestServerParams() 171 localExternalDir, cleanup := testutils.TempDir(t) 172 defer cleanup() 173 params.ExternalIODir = localExternalDir 174 s, db, _ := serverutils.StartServer(t, params) 175 defer s.Stopper().Stop(context.Background()) 176 177 destination := filepath.Join(localExternalDir, filename) 178 writeFile(t, destination, []byte("file exists")) 179 180 err := runCopyFile(t, db, destination) 181 expectedErr := "file already exists" 182 if !testutils.IsError(err, expectedErr) { 183 t.Fatalf(`expected error: %s, got: %s`, expectedErr, err) 184 } 185 } 186 187 func TestNotAdmin(t *testing.T) { 188 defer leaktest.AfterTest(t)() 189 190 params, _ := tests.CreateTestServerParams() 191 localExternalDir, cleanup := testutils.TempDir(t) 192 defer cleanup() 193 params.ExternalIODir = localExternalDir 194 params.Insecure = true 195 s, rootDB, _ := serverutils.StartServer(t, params) 196 defer s.Stopper().Stop(context.Background()) 197 198 _, err := rootDB.Exec("CREATE USER jsmith") 199 require.NoError(t, err) 200 201 pgURL, cleanupGoDB := sqlutils.PGUrlWithOptionalClientCerts( 202 t, s.ServingSQLAddr(), "notAdmin", url.User("jsmith"), false, /* withCerts */ 203 ) 204 defer cleanupGoDB() 205 pgURL.RawQuery = "sslmode=disable" 206 userDB, err := gosql.Open("postgres", pgURL.String()) 207 require.NoError(t, err) 208 defer userDB.Close() 209 210 testFileDir, cleanup2 := testutils.TempDir(t) 211 defer cleanup2() 212 testSendFile := filepath.Join(testFileDir, filename) 213 fileContent := []byte("hello \n blah 1@#% some data hello \n @#%^&&*") 214 writeFile(t, testSendFile, fileContent) 215 216 err = runCopyFile(t, userDB, testSendFile) 217 expectedErr := "only users with the admin role are allowed to upload" 218 if !testutils.IsError(err, expectedErr) { 219 t.Fatalf(`expected error: %s, got: %s`, expectedErr, err) 220 } 221 }