Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/sonar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v6
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ jobs:
go-version-file: 'go.mod'
id: go

- name: Allow toolchain auto-download
run: echo "GOTOOLCHAIN=auto" >> $GITHUB_ENV

- name: Check out code into the Go module directory
uses: actions/checkout@v6

- name: Get dependencies
run: |
go get -v -t ./...
Expand Down
4 changes: 2 additions & 2 deletions arc.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (b arcbuilder) Build() *ArcFSM {

type tuple struct {
Status int
Type interface{}
Type any
}

// ArcFSM is a defined Finite-State-Machine that allows specific mutations of
Expand All @@ -71,7 +71,7 @@ type ArcFSM struct {
}

// IsValidTransition validates status transition without committing the transaction
func (fsm *ArcFSM) IsValidTransition(from Status, to Status) bool {
func (fsm *ArcFSM) IsValidTransition(from, to Status) bool {
s, ok := fsm.updates[from.ShiftStatus()]
if !ok {
return false
Expand Down
6 changes: 3 additions & 3 deletions gen_1_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gen_2_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gen_3_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gen_4_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions gen_string_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ type Currency struct {
Amount int64
}

func (c *Currency) Scan(src interface{}) error {
func (c *Currency) Scan(src any) error {
var s sql.NullString
if err := s.Scan(src); err != nil {
return err
Expand Down
6 changes: 3 additions & 3 deletions shift.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type GenFSM[T primary] struct {
}

// IsValidTransition validates status transition without committing the transaction
func (fsm *GenFSM[T]) IsValidTransition(from Status, to Status) bool {
func (fsm *GenFSM[T]) IsValidTransition(from, to Status) bool {
s, ok := fsm.states[from.ShiftStatus()]
if !ok {
return false
Expand Down Expand Up @@ -293,11 +293,11 @@ func updateTx[T primary](ctx context.Context, tx *sql.Tx, from Status, to Status
type status struct {
st Status
t reflex.EventType
req interface{}
req any
insert bool
next map[Status]bool
}

func sameType(a interface{}, b interface{}) bool {
func sameType(a, b any) bool {
return reflect.TypeOf(a) == reflect.TypeOf(b)
}
4 changes: 2 additions & 2 deletions shift_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type yy y
func Test(t *testing.T) {
cases := []struct {
name string
a interface{}
b interface{}
a any
b any
res bool
}{
{
Expand Down
6 changes: 3 additions & 3 deletions shiftgen/shiftgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func parseInserters() ([]string, error) {
if *inserter != "" {
ii = append(ii, *inserter)
} else if strings.TrimSpace(*inserters) != "" {
for _, i := range strings.Split(*inserters, ",") {
for i := range strings.SplitSeq(*inserters, ",") {
ii = append(ii, strings.TrimSpace(i))
}
}
Expand All @@ -157,7 +157,7 @@ func parseInserters() ([]string, error) {
func parseUpdaters() []string {
var uu []string
if strings.TrimSpace(*updaters) != "" {
for _, u := range strings.Split(*updaters, ",") {
for u := range strings.SplitSeq(*updaters, ",") {
uu = append(uu, strings.TrimSpace(u))
}
}
Expand Down Expand Up @@ -304,7 +304,7 @@ func generateSrc(pkgPath, table string, inserters, updaters []string, statusFiel
}

func execTpl(out io.Writer, tpl string, data Data) error {
t := template.New("").Funcs(map[string]interface{}{
t := template.New("").Funcs(map[string]any{
"col": quoteCol,
})

Expand Down
103 changes: 103 additions & 0 deletions shiftgen/shiftgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,109 @@ import (
"github.com/stretchr/testify/require"
)

func TestToSnakeCase(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{name: "lowercase unchanged", input: "hello", want: "hello"},
{name: "camel to snake", input: "CamelCase", want: "camel_case"},
{name: "multiple words", input: "MyFieldName", want: "my_field_name"},
{name: "acronym", input: "IDField", want: "id_field"},
{name: "already snake", input: "snake_case", want: "snake_case"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := toSnakeCase(tt.input)
if got != tt.want {
t.Errorf("toSnakeCase(%q) = %q, want %q", tt.input, got, tt.want)
}
})
}
}

func TestIDZeroValue(t *testing.T) {
tests := []struct {
name string
idType string
want string
}{
{name: "int64", idType: "int64", want: "0"},
{name: "string", idType: "string", want: `""`},
{name: "unknown type", idType: "uuid", want: ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := Struct{IDType: tt.idType}
got := s.IDZeroValue()
if got != tt.want {
t.Errorf("IDZeroValue() = %q, want %q", got, tt.want)
}
})
}
}

func TestParseUpdaters(t *testing.T) {
tests := []struct {
name string
value string
want []string
}{
{name: "empty", value: "", want: nil},
{name: "single", value: "UpdateReq", want: []string{"UpdateReq"}},
{name: "multiple", value: "UpdateReq,CompleteReq", want: []string{"UpdateReq", "CompleteReq"}},
{name: "with spaces", value: " UpdateReq , CompleteReq ", want: []string{"UpdateReq", "CompleteReq"}},
{name: "whitespace only", value: " ", want: nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
orig := *updaters
*updaters = tt.value
t.Cleanup(func() { *updaters = orig })

got := parseUpdaters()
require.Equal(t, tt.want, got)
})
}
}

func TestParseInserters(t *testing.T) {
tests := []struct {
name string
inserterVal string
insertersVal string
want []string
wantErr bool
}{
{name: "empty", inserterVal: "", insertersVal: "", want: nil},
{name: "single inserter", inserterVal: "InsertReq", insertersVal: "", want: []string{"InsertReq"}},
{name: "multiple inserters", inserterVal: "", insertersVal: "InsertA,InsertB", want: []string{"InsertA", "InsertB"}},
{name: "inserters with spaces", inserterVal: "", insertersVal: " InsertA , InsertB ", want: []string{"InsertA", "InsertB"}},
{name: "both set returns error", inserterVal: "InsertReq", insertersVal: "InsertA", want: nil, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
origInserter := *inserter
origInserters := *inserters
*inserter = tt.inserterVal
*inserters = tt.insertersVal
t.Cleanup(func() {
*inserter = origInserter
*inserters = origInserters
})

got, err := parseInserters()
if tt.wantErr {
require.Error(t, err)
return
}
jtest.RequireNil(t, err)
require.Equal(t, tt.want, got)
})
}
}

func TestGen(t *testing.T) {
cc := []struct {
dir string
Expand Down
22 changes: 11 additions & 11 deletions test_shift.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ func randomInsert(req any) (Inserter[int64], error) {
}

s := reflect.New(reflect.ValueOf(req).Type()).Elem()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
for _, f := range s.Fields() {
f := f
f.Set(randVal(f.Type()))
}
return s.Interface().(Inserter[int64]), nil
Expand Down Expand Up @@ -117,15 +117,15 @@ func buildPaths(states map[int]status, from Status) [][]status {
}

var (
intType = reflect.TypeOf((int)(0))
int64Type = reflect.TypeOf((int64)(0))
float64Type = reflect.TypeOf((float64)(0))
timeType = reflect.TypeOf(time.Time{})
sliceByteType = reflect.TypeOf([]byte(nil))
boolType = reflect.TypeOf(false)
stringType = reflect.TypeOf("")
nullTimeType = reflect.TypeOf(sql.NullTime{})
nullStringType = reflect.TypeOf(sql.NullString{})
intType = reflect.TypeFor[int]()
int64Type = reflect.TypeFor[int64]()
float64Type = reflect.TypeFor[float64]()
timeType = reflect.TypeFor[time.Time]()
sliceByteType = reflect.TypeFor[[]byte]()
boolType = reflect.TypeFor[bool]()
stringType = reflect.TypeFor[string]()
nullTimeType = reflect.TypeFor[sql.NullTime]()
nullStringType = reflect.TypeFor[sql.NullString]()
)

func randVal(t reflect.Type) reflect.Value {
Expand Down
7 changes: 3 additions & 4 deletions test_shift_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ func TestTestFSM(t *testing.T) {
}

func (ii i) GetMetadata(ctx context.Context, tx *sql.Tx, id int64, status shift.Status) ([]byte, error) {
return []byte(fmt.Sprint(id)), nil
return fmt.Append(nil, id), nil
}

func (uu u) GetMetadata(ctx context.Context, tx *sql.Tx, from shift.Status, to shift.Status) ([]byte, error) {
return []byte(fmt.Sprint(uu.ID)), nil
return fmt.Append(nil, uu.ID), nil
}

func TestWithMeta(t *testing.T) {
Expand All @@ -111,8 +111,7 @@ func TestWithMeta(t *testing.T) {
err := shift.TestFSM(t, dbc, fsm)
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

sc, err := events.ToStream(dbc)(context.Background(), "")
require.NoError(t, err)
Expand Down
Loading