repogen/internal/code/package_test.go

239 lines
5.3 KiB
Go
Raw Normal View History

package code_test
import (
"errors"
"go/ast"
"go/parser"
"go/token"
"testing"
2023-05-24 11:04:29 +00:00
"git.kmsign.ru/royalcat/repogen/internal/code"
)
const goImplFile1Data = `
package codepkgsuccess
import (
"math"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type Gender string
const (
GenderMale Gender = "MALE"
GenderFemale Gender = "FEMALE"
)
type User struct {
ID primitive.ObjectID ` + "`json:\"id\"`" + `
Name string ` + "`json:\"name\"`" + `
Gender Gender ` + "`json:\"gender\"`" + `
Birthday time.Time ` + "`json:\"birthday\"`" + `
}
func (u User) Age() int {
return int(math.Floor(time.Since(u.Birthday).Hours() / 24 / 365))
}
type (
Product struct {
ID primitive.ObjectID ` + "`json:\"id\"`" + `
Name string ` + "`json:\"name\"`" + `
Price float64 ` + "`json:\"price\"`" + `
}
Order struct {
ID primitive.ObjectID ` + "`json:\"id\"`" + `
ItemIDs map[primitive.ObjectID]int ` + "`json:\"itemIds\"`" + `
TotalPrice float64 ` + "`json:\"totalPrice\"`" + `
UserID primitive.ObjectID ` + "`json:\"userId\"`" + `
CreatedAt time.Time ` + "`json:\"createdAt\"`" + `
}
)
`
const goImplFile2Data = `
package codepkgsuccess
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type OrderService interface {
CreateOrder(u User, products map[Product]int) Order
}
type OrderServiceImpl struct{}
func (s *OrderServiceImpl) CreateOrder(u User, products map[Product]int) Order {
itemIDs := map[primitive.ObjectID]int{}
var totalPrice float64
for product, amount := range products {
itemIDs[product.ID] = amount
totalPrice += product.Price * float64(amount)
}
return Order{
ID: primitive.NewObjectID(),
ItemIDs: map[primitive.ObjectID]int{},
TotalPrice: totalPrice,
UserID: u.ID,
CreatedAt: time.Now(),
}
}
`
const goImplFile3Data = `
package success
`
const goImplFile4Data = `
package codepkgsuccess
type User struct {
Name string
}
`
const goImplFile5Data = `
package codepkgsuccess
import "go.mongodb.org/mongo-driver/bson/primitive"
type OrderService interface {
CancelOrder(orderID primitive.ObjectID) error
}
`
const goTestFileData = `
package codepkgsuccess
type TestCase struct {
Name string
Params []interface{}
Expected string
Actual string
}
`
var (
goImplFile1 *ast.File
goImplFile2 *ast.File
goImplFile3 *ast.File
goImplFile4 *ast.File
goImplFile5 *ast.File
goTestFile *ast.File
)
func init() {
fset := token.NewFileSet()
goImplFile1, _ = parser.ParseFile(fset, "", goImplFile1Data, parser.ParseComments)
goImplFile2, _ = parser.ParseFile(fset, "", goImplFile2Data, parser.ParseComments)
goImplFile3, _ = parser.ParseFile(fset, "", goImplFile3Data, parser.ParseComments)
goImplFile4, _ = parser.ParseFile(fset, "", goImplFile4Data, parser.ParseComments)
goImplFile5, _ = parser.ParseFile(fset, "", goImplFile5Data, parser.ParseComments)
goTestFile, _ = parser.ParseFile(fset, "", goTestFileData, parser.ParseComments)
}
func TestParsePackage_Success(t *testing.T) {
pkg, err := code.ParsePackage(map[string]*ast.Package{
"codepkgsuccess": {
Files: map[string]*ast.File{
"file1.go": goImplFile1,
"file2.go": goImplFile2,
"file1_test.go": goTestFile,
},
},
})
if err != nil {
t.Fatal(err)
}
if pkg.Name != "codepkgsuccess" {
t.Errorf("expected package name 'codepkgsuccess', got '%s'", pkg.Name)
}
if _, ok := pkg.Structs["User"]; !ok {
t.Error("struct 'User' not found")
}
if _, ok := pkg.Structs["Product"]; !ok {
t.Error("struct 'Product' not found")
}
if _, ok := pkg.Structs["Order"]; !ok {
t.Error("struct 'Order' not found")
}
if _, ok := pkg.Structs["OrderServiceImpl"]; !ok {
t.Error("struct 'OrderServiceImpl' not found")
}
if _, ok := pkg.Interfaces["OrderService"]; !ok {
t.Error("interface 'OrderService' not found")
}
if _, ok := pkg.Structs["TestCase"]; ok {
t.Error("unexpected struct 'TestCase' in test file")
}
}
func TestParsePackage_AmbiguousPackageName(t *testing.T) {
_, err := code.ParsePackage(map[string]*ast.Package{
"codepkgsuccess": {
Files: map[string]*ast.File{
"file1.go": goImplFile1,
"file2.go": goImplFile2,
"file3.go": goImplFile3,
},
},
})
if !errors.Is(err, code.ErrAmbiguousPackageName) {
t.Errorf(
"expected error '%s', got '%s'",
code.ErrAmbiguousPackageName.Error(),
err.Error(),
)
}
}
func TestParsePackage_DuplicateStructs(t *testing.T) {
_, err := code.ParsePackage(map[string]*ast.Package{
"codepkgsuccess": {
Files: map[string]*ast.File{
"file1.go": goImplFile1,
"file2.go": goImplFile2,
"file4.go": goImplFile4,
},
},
})
if !errors.Is(err, code.DuplicateStructError("User")) {
t.Errorf(
"expected error '%s', got '%s'",
code.ErrAmbiguousPackageName.Error(),
err.Error(),
)
}
}
func TestParsePackage_DuplicateInterfaces(t *testing.T) {
_, err := code.ParsePackage(map[string]*ast.Package{
"codepkgsuccess": {
Files: map[string]*ast.File{
"file1.go": goImplFile1,
"file2.go": goImplFile2,
"file5.go": goImplFile5,
},
},
})
if !errors.Is(err, code.DuplicateInterfaceError("OrderService")) {
t.Errorf(
"expected error '%s', got '%s'",
code.ErrAmbiguousPackageName.Error(),
err.Error(),
)
}
}