Compare commits

...

18 Commits

Author SHA1 Message Date
77b8bdf218 removing driver, just generating mock struct args would need an order 2025-09-30 17:48:22 -04:00
2161c201bc reimplementing db tag 2025-09-30 17:39:40 -04:00
935285a9f3 testing without db tags 2025-09-30 17:39:15 -04:00
5f24529730 proper slice allocation 2025-09-30 17:32:27 -04:00
5563e93efd working locally 2025-09-30 17:23:31 -04:00
d0ec9465e2 testing new length 2025-09-30 17:17:45 -04:00
0c4a1abb9a testing any typecast 2025-09-30 17:15:45 -04:00
791ffad0e3 testing 2025-09-30 17:13:52 -04:00
2415af38b2 Fixing struct generation
- ready to test
- slice size bugfixes
- appending empty struct before filling it out
2025-09-30 17:09:19 -04:00
053f5b5fd8 no more index check 2025-09-30 16:25:54 -04:00
6326711424 adding ok check to prevent panics 2025-09-30 11:47:38 -04:00
6a9cdafcf1 testing better types 2025-09-30 11:43:40 -04:00
5e2ddecdcc dont elem slice 2025-09-30 11:41:28 -04:00
9033530a55 testing any type for resturned structs 2025-09-30 11:33:59 -04:00
6bbb452b03 argument type fix 2025-09-30 11:26:54 -04:00
21b1291dbc struct name revert 2025-09-30 11:20:30 -04:00
c62da47a31 ready for tests 2025-09-30 11:12:47 -04:00
ff62b371c9 adding new functionality for mocks
- working through insert logic
- ideally return struct with 'good' fields
- also return list of args to prevent relooping
2025-09-29 15:47:51 -04:00
2 changed files with 96 additions and 20 deletions

2
.gitignore vendored
View File

@@ -25,3 +25,5 @@ go.work.sum
# env file
.env
#ignore test files
cmd/

114
lazy.go
View File

@@ -17,51 +17,69 @@ const (
KEY_VALUE = "key" //tag value for LAZY_TAG
)
var (
ErrBadExample = errors.New("example field must be a non-nil struct")
ErrMissingKeys = errors.New("there must be a key for each row requested with RowCount")
//contains placeholder to inject type on runtime
ErrUnsupportedType = errors.New("type: %s is not yet supported")
)
// mock data generated based on config
type Mock struct {
type RowMock struct {
Query string
Columns []string
Rows [][]driver.Value
}
// configuration for RandomGenerate
type Config struct {
type RowConfig struct {
Query string
Example any
Keys []any //length of keys must = RowCount, if set
Keys []any
RowCount int
}
type StructConfig struct {
Query string
Example any
RowCount int
}
type StructMock struct {
Query string
MockStructs []any
}
// generates mock data based on configuration to be used for sqlmock
func RandomGenerate(m Config) (*Mock, error) {
func RandomRows(r RowConfig) (*RowMock, error) {
//example struct cannot be nil and must be a struct
if m.Example == nil {
return nil, errors.New("example value cannot be nil")
if r.Example == nil {
return nil, ErrBadExample
}
if reflect.ValueOf(m.Example).Kind() != reflect.Struct {
return nil, errors.New("example value must be a struct")
if reflect.ValueOf(r.Example).Kind() != reflect.Struct {
return nil, ErrBadExample
}
//any weirdness, just pull one row
if m.RowCount <= 0 {
m.RowCount = 1
if r.RowCount <= 0 {
r.RowCount = 1
}
//if keys are set, ensure there are enough to populate requested rows
primaryKey := false
if len(m.Keys) > 0 {
if len(r.Keys) > 0 {
primaryKey = true
if len(m.Keys) != m.RowCount {
return nil, errors.New("you must provide a key for each row")
if len(r.Keys) != r.RowCount {
return nil, ErrMissingKeys
}
}
retType := reflect.TypeOf(m.Example)
retType := reflect.TypeOf(r.Example)
maxFieldCount := retType.NumField()
columns := make([]string, 0, maxFieldCount)
rows := make([][]driver.Value, 0)
for y := 0; y < m.RowCount; y++ {
for y := 0; y < r.RowCount; y++ {
rows = append(rows, make([]driver.Value, 0))
for x := 0; x < maxFieldCount; x++ {
field := retType.Field(x)
@@ -77,29 +95,85 @@ func RandomGenerate(m Config) (*Mock, error) {
//if field has lazy:"key" tag and tags are present inject primary key
if field.Tag.Get(LAZY_TAG) == KEY_VALUE && primaryKey {
rows[y] = append(rows[y], m.Keys[y])
rows[y] = append(rows[y], r.Keys[y])
continue
}
//generate random values
nv := kindToRandom(field)
if nv == nil {
return nil, fmt.Errorf("could not match type: %s", retType.Name())
return nil, fmt.Errorf(ErrUnsupportedType.Error(), field.Type.Name())
}
rows[y] = append(rows[y], nv)
}
}
return &Mock{
return &RowMock{
//sql is rebound and escaped for sqlmock.ExpectQuery
Query: sqlx.Rebind(sqlx.AT, regexp.QuoteMeta(m.Query)),
Query: sqlx.Rebind(sqlx.AT, regexp.QuoteMeta(r.Query)),
Columns: columns,
Rows: rows,
}, nil
}
// converts basic reflect Kind's to psuedo-random data, slices are given a random amount of entries
// generates mock data for insert statements to be used for sqlmock, it also returns a slice of
// example structs with mock data
func RandomStruct(c StructConfig) (*StructMock, error) {
//make sure we have an example struct
if c.Example == nil {
return nil, ErrBadExample
}
if reflect.ValueOf(c.Example).Kind() != reflect.Struct {
return nil, ErrBadExample
}
//we need at least one row
if c.RowCount <= 0 {
c.RowCount = 1
}
//get example type and number of fields
retType := reflect.TypeOf(c.Example)
maxFieldCount := retType.NumField()
//create slice of example structs
ft := reflect.SliceOf(retType)
filled := reflect.MakeSlice(ft, 0, c.RowCount)
for x := 0; x < c.RowCount; x++ {
//add empty example struct
filled = reflect.Append(filled, reflect.ValueOf(c.Example))
for y := 0; y < maxFieldCount; y++ {
field := retType.Field(y)
//get random value
nv := kindToRandom(field)
if nv == nil {
return nil, fmt.Errorf(ErrUnsupportedType.Error(), field.Type.Name())
}
if filled.Index(x).Field(y).CanSet() {
filled.Index(x).Field(y).Set(reflect.ValueOf(nv))
}
}
}
//convert reflect.Value to []any
fl := filled.Len()
retStructs := make([]any, fl)
for x := 0; x < fl; x++ {
retStructs[x] = filled.Index(x).Interface()
}
return &StructMock{
Query: sqlx.Rebind(sqlx.AT, regexp.QuoteMeta(c.Query)),
MockStructs: retStructs,
}, nil
}
// converts basic reflect Kind's to psuedo-random data, it is super basic and supports very basic types. Slices and arrays
// are supported, slices will get 1-10 entries and arrays will fill length
func kindToRandom(field reflect.StructField) any {
kind := field.Type.Kind()
switch kind {