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() } `) 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: source.Id", "&TargetAddress{City: source.Address.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): List { return values.mapTo>() } fun mapping(values: Map): Map { return values.mapTo>() } `) 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() } `) 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() } `) 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() }`, `package demo enum Source { Ready, Failed } enum Target { Ready } fun convert(value: Source): Target { return value.mapTo() }`, } { 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() } fun toDomain(value: Row): Domain { return value.mapTo() }`) 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) } }