xorm/tests/ydbtest/e2e_test.go

228 lines
5.0 KiB
Go

package ydb
import (
"context"
"fmt"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"xorm.io/xorm"
"xorm.io/xorm/retry"
_ "github.com/ydb-platform/ydb-go-sdk/v3"
)
type e2e struct {
ctx context.Context
engines *EngineWithMode
}
func TestE2E(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
scope := &e2e{
ctx: ctx,
engines: NewEngineWithMode(ctx, connString),
}
t.Run("create-engine", func(t *testing.T) {
engine, err := scope.engines.GetDefaultEngine()
require.NoError(t, err)
err = engine.PingContext(ctx)
require.NoError(t, err)
err = engine.Close()
require.NoError(t, err)
})
t.Run("e2e", func(t *testing.T) {
t.Run("prepare-stage", func(t *testing.T) {
t.Run("scheme", func(t *testing.T) {
err := scope.prepareScheme()
require.NoError(t, err)
})
})
t.Run("fill-stage", func(t *testing.T) {
err := scope.fill()
require.NoError(t, err)
})
t.Run("query-stage", func(t *testing.T) {
t.Run("explain", func(t *testing.T) {
engine, err := scope.engines.GetExplainQueryEngine()
require.NoError(t, err)
var (
ast string
plan string
)
r, err := engine.
Table(&Episodes{}).
Cols("views").
Where("series_id = ?", uuid.New()).
And("season_id = ?", uuid.New()).
And("episode_id = ?", uuid.New()).
Rows(&struct {
Ast string
Plan string
}{})
require.NoError(t, err)
require.True(t, r.Next())
err = r.Scan(&ast, &plan)
require.NoError(t, err)
t.Logf("ast = %v\n", ast)
t.Logf("plan = %v\n", plan)
})
t.Run("increment", func(t *testing.T) {
t.Run("views", func(t *testing.T) {
engine, err := scope.engines.GetDataQueryEngine()
require.NoError(t, err)
err = engine.DoTx(scope.ctx, func(ctx context.Context, session *xorm.Session) (err error) {
var epData Episodes
_, err = session.Get(&epData)
if err != nil {
return err
}
session.
Table(Episodes{}).
Cols("views").
Where("series_id = ?", epData.SeriesID).
And("season_id = ?", epData.SeasonID).
And("episode_id = ?", epData.EpisodeID).
Prepare()
rows, err := session.Rows(&Episodes{})
if err != nil {
return err
}
defer func() {
_ = rows.Close()
}()
for rows.Next() {
var ep Episodes
if err = rows.Scan(&ep); err != nil {
return fmt.Errorf("cannot scan views: %w", err)
}
t.Logf("got views: %+v\n", ep.Views)
// increase views by 1
_, err = session.
Table(Episodes{}).
Where("series_id = ?", epData.SeriesID).
And("season_id = ?", epData.SeasonID).
And("episode_id = ?", epData.EpisodeID).
Incr("views", uint64(1)).
Update(&Episodes{})
if err != nil {
return fmt.Errorf("cannot increase views by 1 %w", err)
}
}
return nil
}, retry.WithID("e2e-test-query-increment"),
retry.WithIdempotent(true))
require.NoError(t, err)
})
})
t.Run("select", func(t *testing.T) {
engine, err := scope.engines.GetScanQueryEngine()
require.NoError(t, err)
err = engine.DoTx(scope.ctx, func(ctx context.Context, session *xorm.Session) (err error) {
has, err := session.
Table(Episodes{}).
Where("views = ?", uint64(1)).
Exist()
if err != nil {
return err
}
if !has {
return fmt.Errorf("expected record exists")
}
rows, err := session.
Table(Episodes{}).
Cols("title", "air_date", "views").
Where("views = ?", uint64(1)).
Rows(&Episodes{})
if err != nil {
return err
}
defer func() {
_ = rows.Close()
}()
for rows.Next() {
var (
title string
air_date time.Time
views uint64
)
if err := rows.Scan(&title, &air_date, &views); err != nil {
return err
}
t.Logf("> %v %v %v\n", title, views, air_date.Format("2006-01-02"))
}
return nil
}, retry.WithID("e2e-test-query-select"),
retry.WithIdempotent(true))
require.NoError(t, err)
})
})
t.Run("close-engines", func(t *testing.T) {
err := scope.engines.Close()
require.NoError(t, err)
})
})
}
func (scope *e2e) fill() error {
engine, err := scope.engines.GetDataQueryEngine()
if err != nil {
return err
}
series, seasons, episodes := getData()
err = engine.DoTx(scope.ctx, func(ctx context.Context, session *xorm.Session) (err error) {
_, err = session.Insert(series, seasons, episodes)
return err
},
retry.WithID("e2e-test-fill-stage"),
retry.WithIdempotent(true))
return err
}
func (scope *e2e) prepareScheme() error {
engine, err := scope.engines.GetSchemeQueryEngine()
if err != nil {
return err
}
if err = engine.DropTables(&Series{}, &Seasons{}, &Episodes{}); err != nil {
return err
}
if err = engine.CreateTables(&Series{}, &Seasons{}, &Episodes{}); err != nil {
return err
}
return nil
}