2023-07-03 18:34:19 +03:00
|
|
|
package cli_test
|
|
|
|
|
|
|
|
import (
|
2023-07-09 04:34:53 +03:00
|
|
|
"context"
|
2023-07-03 18:34:19 +03:00
|
|
|
"testing"
|
|
|
|
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/stretchr/testify/require"
|
2023-07-09 04:34:53 +03:00
|
|
|
|
|
|
|
"github.com/neilotoole/sq/cli/flag"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/cli/testrun"
|
|
|
|
"github.com/neilotoole/sq/libsq/core/options"
|
2023-07-03 18:34:19 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/core/stringz"
|
|
|
|
"github.com/neilotoole/sq/libsq/driver"
|
|
|
|
"github.com/neilotoole/sq/testh"
|
2023-11-20 04:06:36 +03:00
|
|
|
"github.com/neilotoole/sq/testh/proj"
|
2023-07-03 18:34:19 +03:00
|
|
|
"github.com/neilotoole/sq/testh/sakila"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TestCmdConfigSet verifies that setting config options actually takes effect.
|
|
|
|
// In this test, we use driver.OptResultColRename, setting that template such
|
|
|
|
// that the column name is transformed to uppercase.
|
|
|
|
func TestCmdConfigSet(t *testing.T) {
|
|
|
|
th := testh.New(t)
|
|
|
|
src := th.Source(sakila.SL3)
|
|
|
|
|
|
|
|
tr := testrun.New(th.Context, t, nil).Hush().Add(*src)
|
|
|
|
err := tr.Exec(".actor | .[0]")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
got := tr.Out.String()
|
|
|
|
require.Contains(t, got, "actor_id")
|
|
|
|
require.NotContains(t, got, "ACTOR_ID")
|
|
|
|
|
|
|
|
tr = testrun.New(th.Context, t, tr)
|
2023-07-09 04:34:53 +03:00
|
|
|
const tpl = `{{.Name | upper}}_{{.Alpha}}`
|
2023-07-03 18:34:19 +03:00
|
|
|
err = tr.Exec("config", "set", driver.OptResultColRename.Key(), stringz.ShellEscape(tpl))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tr = testrun.New(th.Context, t, tr)
|
|
|
|
err = tr.Exec(".actor | .[0]")
|
|
|
|
require.NoError(t, err)
|
|
|
|
got = tr.Out.String()
|
2023-07-09 04:34:53 +03:00
|
|
|
require.Contains(t, got, "ACTOR_ID_A")
|
2023-07-03 18:34:19 +03:00
|
|
|
require.NotContains(t, got, "actor_id")
|
|
|
|
}
|
2023-07-09 04:34:53 +03:00
|
|
|
|
|
|
|
func TestConfigSetBaseOptOnSourceIsError(t *testing.T) {
|
|
|
|
const handle = "@actor"
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
tr := testrun.New(ctx, t, nil).Hush()
|
|
|
|
|
|
|
|
fp := proj.Abs("drivers/csv/testdata/sakila-csv/actor.csv")
|
|
|
|
require.NoError(t, tr.Exec("add", fp, "--handle="+handle))
|
|
|
|
|
|
|
|
// Note that driver.OptResultColRename is not a source tag.
|
|
|
|
require.False(t, driver.OptResultColRename.HasTag(options.TagSource))
|
|
|
|
|
|
|
|
const tpl = "{{.Name}}"
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
driver.OptResultColRename.Key(), tpl,
|
|
|
|
), "should work for base config")
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
err := tr.Exec("config", "set",
|
|
|
|
"--"+flag.ConfigSrc, handle,
|
|
|
|
driver.OptResultColRename.Key(), tpl,
|
|
|
|
)
|
|
|
|
require.Error(t, err, "should NOT work for source config")
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestSourceOptOverridesBaseOpt tests that source-specific opts override base opts.
|
|
|
|
func TestSourceOptOverridesBaseOpt(t *testing.T) {
|
|
|
|
const handle = "@actor"
|
|
|
|
|
|
|
|
opt := driver.OptIngestColRename
|
|
|
|
require.True(t, opt.HasTag(options.TagSource),
|
|
|
|
"verify that the opt applies to sources")
|
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
fp string
|
|
|
|
tblName string
|
|
|
|
}{
|
|
|
|
{sakila.PathXLSXActorHeader, ".actor"},
|
|
|
|
{sakila.PathCSVActor, ".data"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
tc := tc
|
|
|
|
t.Run(tc.fp, func(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
tr := testrun.New(ctx, t, nil).Hush()
|
|
|
|
|
|
|
|
fp := proj.Abs(tc.fp)
|
|
|
|
require.NoError(t, tr.Exec("add", fp, "--handle="+handle))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
defaultHeaders := sakila.TblActorCols()
|
|
|
|
data := tr.BindCSV()
|
|
|
|
require.Equal(t, defaultHeaders, data[0])
|
|
|
|
|
|
|
|
const baseTpl = "base_{{.Name}}"
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
opt.Key(), baseTpl,
|
|
|
|
))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
wantBaseHeaders := stringz.PrefixSlice(sakila.TblActorCols(), "base_")
|
|
|
|
data = tr.BindCSV()
|
|
|
|
require.Equal(t, wantBaseHeaders, data[0])
|
|
|
|
|
|
|
|
const srcTpl = "src_{{.Name}}"
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
"--"+flag.ConfigSrc, handle,
|
|
|
|
opt.Key(), srcTpl,
|
|
|
|
))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
wantSrcHeaders := stringz.PrefixSlice(sakila.TblActorCols(), "src_")
|
|
|
|
data = tr.BindCSV()
|
|
|
|
require.Equal(t, wantSrcHeaders, data[0])
|
|
|
|
|
|
|
|
// Unset base opt
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
opt.Key(), "",
|
|
|
|
))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
data = tr.BindCSV()
|
|
|
|
require.Equal(t, wantSrcHeaders, data[0], "should still show src headers")
|
|
|
|
|
|
|
|
// Unset src opt
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
"--"+flag.ConfigSrc, handle,
|
|
|
|
opt.Key(), "",
|
|
|
|
))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
data = tr.BindCSV()
|
|
|
|
require.Equal(t, defaultHeaders, data[0], "should be back to default headers")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestColRenameOptsInteraction tests the interaction of
|
|
|
|
// driver.OptIngestColRename and driver.OptResultColRename.
|
|
|
|
func TestColRenameOptsInteraction(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
fp string
|
|
|
|
tblName string
|
|
|
|
}{
|
|
|
|
{sakila.PathXLSXActorHeader, ".actor"},
|
|
|
|
{sakila.PathCSVActor, ".data"},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
tc := tc
|
|
|
|
t.Run(tc.fp, func(t *testing.T) {
|
|
|
|
ctx := context.Background()
|
|
|
|
tr := testrun.New(ctx, t, nil)
|
|
|
|
|
|
|
|
fp := proj.Abs(tc.fp)
|
|
|
|
err := tr.Exec("add", fp)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
const ingestTpl = "x_{{.Name}}"
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
driver.OptIngestColRename.Key(), ingestTpl,
|
|
|
|
))
|
|
|
|
|
|
|
|
const resultTpl = "{{.Name}}_y"
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("config", "set",
|
|
|
|
driver.OptResultColRename.Key(), resultTpl,
|
|
|
|
))
|
|
|
|
|
|
|
|
tr = testrun.New(ctx, t, tr)
|
|
|
|
require.NoError(t, tr.Exec("--csv", tc.tblName))
|
|
|
|
wantHeaders := []string{"x_actor_id_y", "x_first_name_y", "x_last_name_y", "x_last_update_y"}
|
|
|
|
data := tr.BindCSV()
|
|
|
|
require.Equal(t, wantHeaders, data[0])
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|