159 lines
4.7 KiB
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)
|
|
}
|
|
}
|