gotlin/internal/lang/mapping_test.go

159 lines
4.7 KiB
Go

package lang
import (
"strings"
"testing"
)
func TestGenerateRecursiveClassMapping(t *testing.T) {
prog, err := Parse(`
package demo
data class SourceAddress(var city: String)
data class TargetAddress(var city: String)
data class Source(var id: String, var address: *SourceAddress)
data class Target(var address: *TargetAddress, var id: String)
fun convert(source: *Source): *Target { return source.mapTo<Target>() }
`)
if err != nil {
t.Fatal(err)
}
out, err := GenerateGo(prog)
if err != nil {
t.Fatal(err)
}
code := string(out)
for _, want := range []string{"gotlinMap1(source)", "Address:", "Id: value.Id", "TargetAddress{City: value.City}"} {
if !strings.Contains(code, want) {
t.Fatalf("missing %q:\n%s", want, code)
}
}
}
func TestGenerateListAndMapMapping(t *testing.T) {
prog, err := Parse(`
package demo
data class Source(var id: String)
data class Target(var id: String)
fun list(values: List<*Source>): List<*Target> { return values.mapTo<List<*Target>>() }
fun mapping(values: Map<String, *Source>): Map<String, *Target> { return values.mapTo<Map<String, *Target>>() }
`)
if err != nil {
t.Fatal(err)
}
out, err := GenerateGo(prog)
if err != nil {
t.Fatal(err)
}
for _, want := range []string{"for _, item := range values", "for key, item := range values", "result[key]"} {
if !strings.Contains(string(out), want) {
t.Fatalf("missing %q:\n%s", want, out)
}
}
}
func TestGenerateRecursiveEnumMapping(t *testing.T) {
prog, err := Parse(`
package demo
enum Source { Ready(String), Failed(String) }
enum Target { Ready(String), Failed(String), Pending }
fun convert(value: Source): Target { return value.mapTo<Target>() }
`)
if err != nil {
t.Fatal(err)
}
out, err := GenerateGo(prog)
if err != nil {
t.Fatal(err)
}
for _, want := range []string{"case *SourceReady:", "return &TargetReady{Value0: value.Value0}", "case *SourceFailed:"} {
if !strings.Contains(string(out), want) {
t.Fatalf("missing %q:\n%s", want, out)
}
}
}
func TestMappingReportsNestedFieldPath(t *testing.T) {
prog, err := Parse(`
package demo
data class SourceAddress(var zip: String)
data class TargetAddress(var zip: Int)
data class Source(var address: *SourceAddress)
data class Target(var address: *TargetAddress)
fun convert(value: *Source): *Target { return value.mapTo<Target>() }
`)
if err != nil {
t.Fatal(err)
}
_, err = GenerateGo(prog)
if err == nil || !strings.Contains(err.Error(), "Source.address.zip") || !strings.Contains(err.Error(), "String is incompatible with Int") {
t.Fatalf("unexpected mapping error: %v", err)
}
}
func TestMappingRejectsMissingFieldAndEnumVariant(t *testing.T) {
for _, source := range []string{
`package demo data class Source(var id: String) data class Target(var id: String, var name: String) fun convert(value: *Source): *Target { return value.mapTo<Target>() }`,
`package demo enum Source { Ready, Failed } enum Target { Ready } fun convert(value: Source): Target { return value.mapTo<Target>() }`,
} {
prog, err := Parse(source)
if err != nil {
t.Fatal(err)
}
if _, err = GenerateGo(prog); err == nil {
t.Fatalf("expected mapping error for %s", source)
}
}
}
func TestMapStringBackedEnumToAndFromString(t *testing.T) {
prog, err := Parse(`package demo
enum Status { PendingReservation, Initiated }
data class Domain(var status: Status)
data class Row(var status: String)
fun toRow(value: *Domain): *Row { return value.mapTo<Row>() }
fun toDomain(value: *Row): *Domain { return value.mapTo<Domain>() }`)
if err != nil {
t.Fatal(err)
}
out, err := GenerateGo(prog)
if err != nil {
t.Fatal(err)
}
for _, want := range []string{`return string(source)`, `case "PendingReservation":`, `return StatusPendingReservation`} {
if !strings.Contains(string(out), want) {
t.Fatalf("missing %q:\n%s", want, out)
}
}
}
func TestMapToInfersExpectedTargetType(t *testing.T) {
prog, err := Parse(`package demo
data class Source(var id: String)
data class Target(var id: String)
data class Wrapper(var target: *Target)
fun returned(value: *Source): *Target { return value.mapTo() }
fun wrapped(value: *Source): *Wrapper { return Wrapper(value.mapTo()) }
fun local(value: *Source): *Target { val target: *Target = value.mapTo(); return target }`)
if err != nil {
t.Fatal(err)
}
out, err := GenerateGo(prog)
if err != nil {
t.Fatal(err)
}
if strings.Count(string(out), "gotlinMap1(value)") < 3 {
t.Fatalf("expected inferred mapping calls:\n%s", out)
}
}
func TestMapToWithoutTargetContextHasHelpfulError(t *testing.T) {
prog, err := Parse(`package demo
fun convert(value: *Source) { val target = value.mapTo() }`)
if err != nil {
t.Fatal(err)
}
_, err = GenerateGo(prog)
if err == nil || !strings.Contains(err.Error(), "target type cannot be inferred") {
t.Fatalf("unexpected error: %v", err)
}
}