mirror of
https://github.com/neilotoole/sq.git
synced 2024-12-27 18:22:51 +03:00
2f2dfd6e47
- Implement `sq diff --data`.
229 lines
6.0 KiB
Go
229 lines
6.0 KiB
Go
package source
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"runtime"
|
|
"testing"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/lg"
|
|
"github.com/neilotoole/sq/testh/tutil"
|
|
|
|
"github.com/neilotoole/slogt"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/neilotoole/sq/testh/proj"
|
|
"github.com/neilotoole/sq/testh/sakila"
|
|
"github.com/neilotoole/sq/testh/testsrc"
|
|
)
|
|
|
|
// Export for testing.
|
|
var (
|
|
FilesDetectTypeFn = func(fs *Files, ctx context.Context, loc string) (typ DriverType, ok bool, err error) {
|
|
return fs.detectType(ctx, loc)
|
|
}
|
|
GroupsFilterOnlyDirectChildren = groupsFilterOnlyDirectChildren
|
|
)
|
|
|
|
func TestFiles_Open(t *testing.T) {
|
|
ctx := lg.NewContext(context.Background(), slogt.New(t))
|
|
|
|
fs, err := NewFiles(ctx)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { assert.NoError(t, fs.Close()) })
|
|
|
|
src1 := &Source{
|
|
Location: proj.Abs(testsrc.PathXLSXTestHeader),
|
|
}
|
|
|
|
f, err := fs.openLocation(src1.Location)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { assert.NoError(t, f.Close()) })
|
|
require.Equal(t, src1.Location, f.Name())
|
|
|
|
src2 := &Source{
|
|
Location: sakila.URLActorCSV,
|
|
}
|
|
|
|
f2, err := fs.openLocation(src2.Location)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { assert.NoError(t, f2.Close()) })
|
|
|
|
b, err := io.ReadAll(f2)
|
|
require.NoError(t, err)
|
|
require.Equal(t, proj.ReadFile(sakila.PathCSVActor), b)
|
|
}
|
|
|
|
func TestParseLoc(t *testing.T) {
|
|
const (
|
|
dbuser = "sakila"
|
|
dbpass = "p_ssW0rd"
|
|
)
|
|
|
|
testCases := []struct {
|
|
loc string
|
|
want parsedLoc
|
|
wantErr bool
|
|
windows bool
|
|
}{
|
|
{
|
|
loc: "/path/to/sakila.xlsx",
|
|
want: parsedLoc{name: "sakila", ext: ".xlsx"},
|
|
},
|
|
{
|
|
loc: "relative/path/to/sakila.xlsx",
|
|
want: parsedLoc{name: "sakila", ext: ".xlsx"},
|
|
},
|
|
{
|
|
loc: "./relative/path/to/sakila.xlsx",
|
|
want: parsedLoc{name: "sakila", ext: ".xlsx"},
|
|
},
|
|
{
|
|
loc: "https://server:8080/path/to/sakila.xlsx",
|
|
want: parsedLoc{scheme: "https", hostname: "server", port: 8080, name: "sakila", ext: ".xlsx"},
|
|
},
|
|
{
|
|
loc: "http://server/path/to/sakila.xlsx?param=val¶m2=val2",
|
|
want: parsedLoc{scheme: "http", hostname: "server", name: "sakila", ext: ".xlsx"},
|
|
},
|
|
{
|
|
loc: "sqlite3:/path/to/sakila.db",
|
|
wantErr: true,
|
|
}, // the scheme is malformed (should be "sqlite3://...")
|
|
{
|
|
loc: "sqlite3:///path/to/sakila.sqlite",
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", ext: ".sqlite",
|
|
dsn: "/path/to/sakila.sqlite",
|
|
},
|
|
},
|
|
{
|
|
loc: `sqlite3://C:\path\to\sakila.sqlite`,
|
|
windows: true,
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", ext: ".sqlite",
|
|
dsn: `C:\path\to\sakila.sqlite`,
|
|
},
|
|
},
|
|
{
|
|
loc: `sqlite3://C:\path\to\sakila.sqlite?param=val`,
|
|
windows: true,
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", ext: ".sqlite",
|
|
dsn: `C:\path\to\sakila.sqlite?param=val`,
|
|
},
|
|
},
|
|
{
|
|
loc: "sqlite3:///path/to/sakila",
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", dsn: "/path/to/sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "sqlite3://path/to/sakila.db",
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", ext: ".db", dsn: "path/to/sakila.db",
|
|
},
|
|
},
|
|
{
|
|
loc: "sqlite3:///path/to/sakila.db",
|
|
want: parsedLoc{
|
|
typ: typeSL3, scheme: "sqlite3", name: "sakila", ext: ".db", dsn: "/path/to/sakila.db",
|
|
},
|
|
},
|
|
{
|
|
loc: "sqlserver://sakila:p_ssW0rd@localhost?database=sakila",
|
|
want: parsedLoc{
|
|
typ: typeMS, scheme: "sqlserver", user: dbuser, pass: dbpass, hostname: "localhost",
|
|
name: "sakila", dsn: "sqlserver://sakila:p_ssW0rd@localhost?database=sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "sqlserver://sakila:p_ssW0rd@server:1433?database=sakila",
|
|
want: parsedLoc{
|
|
typ: typeMS, scheme: "sqlserver", user: dbuser, pass: dbpass, hostname: "server",
|
|
port: 1433, name: "sakila",
|
|
dsn: "sqlserver://sakila:p_ssW0rd@server:1433?database=sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "postgres://sakila:p_ssW0rd@localhost/sakila?sslmode=disable",
|
|
want: parsedLoc{
|
|
typ: typePg, scheme: "postgres", user: dbuser, pass: dbpass, hostname: "localhost",
|
|
name: "sakila", dsn: "dbname=sakila host=localhost password=p_ssW0rd sslmode=disable user=sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "postgres://sakila:p_ssW0rd@server:5432/sakila?sslmode=disable",
|
|
want: parsedLoc{
|
|
typ: typePg, scheme: "postgres", user: dbuser, pass: dbpass, hostname: "server", port: 5432,
|
|
name: "sakila",
|
|
dsn: "dbname=sakila host=server password=p_ssW0rd port=5432 sslmode=disable user=sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "mysql://sakila:p_ssW0rd@localhost/sakila",
|
|
want: parsedLoc{
|
|
typ: typeMy, scheme: "mysql", user: dbuser, pass: dbpass, hostname: "localhost",
|
|
name: "sakila", dsn: "sakila:p_ssW0rd@tcp(localhost:3306)/sakila",
|
|
},
|
|
},
|
|
{
|
|
loc: "mysql://sakila:p_ssW0rd@server:3306/sakila",
|
|
want: parsedLoc{
|
|
typ: typeMy, scheme: "mysql", user: dbuser, pass: dbpass, hostname: "server", port: 3306,
|
|
name: "sakila", dsn: "sakila:p_ssW0rd@tcp(server:3306)/sakila",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tc.loc, func(t *testing.T) {
|
|
if tc.windows && runtime.GOOS != "windows" {
|
|
return
|
|
}
|
|
|
|
tc.want.loc = tc.loc // set this here rather than verbosely in the setup
|
|
got, gotErr := parseLoc(tc.loc)
|
|
if tc.wantErr {
|
|
require.Error(t, gotErr)
|
|
require.Nil(t, got)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, gotErr)
|
|
require.Equal(t, tc.want, *got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGroupsFilterOnlyDirectChildren(t *testing.T) {
|
|
testCases := []struct {
|
|
parent string
|
|
groups []string
|
|
want []string
|
|
}{
|
|
{
|
|
parent: "/",
|
|
groups: []string{"/", "prod", "prod/customer", "staging"},
|
|
want: []string{"prod", "staging"},
|
|
},
|
|
{
|
|
parent: "prod",
|
|
groups: []string{"/", "prod", "prod/customer", "prod/backup", "staging"},
|
|
want: []string{"prod/customer", "prod/backup"},
|
|
},
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
tc := tc
|
|
t.Run(tutil.Name(i, tc.want), func(t *testing.T) {
|
|
got := GroupsFilterOnlyDirectChildren(tc.parent, tc.groups)
|
|
require.EqualValues(t, tc.want, got)
|
|
})
|
|
}
|
|
}
|