151 lines
4.3 KiB
Go
151 lines
4.3 KiB
Go
package lang
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestGenerateRustStyleEnumAndExhaustiveMatch(t *testing.T) {
|
|
prog, err := Parse(`
|
|
package demo
|
|
enum PaymentResult { Accepted(String), Rejected(String), Pending }
|
|
fun describe(result: PaymentResult): String {
|
|
var description = ""
|
|
match (result) {
|
|
PaymentResult.Accepted(id) -> { description = id }
|
|
PaymentResult.Rejected(reason) -> { description = reason }
|
|
PaymentResult.Pending -> { description = "pending" }
|
|
}
|
|
return description
|
|
}
|
|
fun main() { println(describe(PaymentResult.Accepted("p1"))) }
|
|
`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out, err := GenerateGo(prog)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"type PaymentResult interface", "type PaymentResultAccepted struct", "&PaymentResultAccepted{Value0: \"p1\"}", "case *PaymentResultRejected:", "reason := gotlinMatch1.Value0"} {
|
|
if !strings.Contains(string(out), want) {
|
|
t.Fatalf("missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRejectNonExhaustiveEnumMatch(t *testing.T) {
|
|
prog, err := Parse(`package demo
|
|
enum Result { Ok, Error(String) }
|
|
fun use(result: Result) { match (result) { Result.Ok -> { println("ok") } } }`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = GenerateGo(prog)
|
|
if err == nil || !strings.Contains(err.Error(), "missing Error") {
|
|
t.Fatalf("expected exhaustive-match error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRejectWrongVariantPayloadCount(t *testing.T) {
|
|
prog, err := Parse(`package demo
|
|
enum Outcome { Ok(String) }
|
|
fun main() { val result = Outcome.Ok() }`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = GenerateGo(prog)
|
|
if err == nil || !strings.Contains(err.Error(), "expects 1 values") {
|
|
t.Fatalf("expected payload error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRejectDoubleColonEnumSyntax(t *testing.T) {
|
|
_, err := Parse(`package demo enum State { Ready } fun main() { println(State::Ready) }`)
|
|
if err == nil {
|
|
t.Fatal("deprecated double-colon enum syntax parsed")
|
|
}
|
|
}
|
|
|
|
func TestPayloadlessEnumUsesExactVariantStrings(t *testing.T) {
|
|
prog, err := Parse(`package demo
|
|
enum Status { PendingReservation, Initiated }
|
|
fun main() { println(Status.PendingReservation) }`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out, err := GenerateGo(prog)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{`type Status string`, `StatusPendingReservation`, `"PendingReservation"`, `StatusInitiated`, `"Initiated"`} {
|
|
if !strings.Contains(string(out), want) {
|
|
t.Fatalf("missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGenerateExhaustiveMatchExpression(t *testing.T) {
|
|
prog, err := Parse(`package demo
|
|
enum AccountType { BASIC, SAVINGS }
|
|
fun interestRate(accountType: AccountType): Double {
|
|
return match (accountType) {
|
|
AccountType.BASIC -> 0.0
|
|
AccountType.SAVINGS -> 0.02
|
|
}
|
|
}`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out, err := GenerateGo(prog)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"func() float64", "case AccountTypeBASIC:", "return 0.0", "case AccountTypeSAVINGS:", "return 0.02", `panic("unreachable exhaustive match")`} {
|
|
if !strings.Contains(string(out), want) {
|
|
t.Fatalf("missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGeneratePayloadMatchExpression(t *testing.T) {
|
|
prog, err := Parse(`package demo
|
|
enum Outcome { Success(String), Failure(String) }
|
|
fun message(outcome: Outcome): String {
|
|
return match (outcome) {
|
|
Outcome.Success(value) -> value
|
|
Outcome.Failure(reason) -> reason
|
|
}
|
|
}`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out, err := GenerateGo(prog)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"switch gotlinMatch", "value := gotlinMatch", "return value", "return reason"} {
|
|
if !strings.Contains(string(out), want) {
|
|
t.Fatalf("missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRejectInvalidMatchExpression(t *testing.T) {
|
|
for _, test := range []struct {
|
|
source string
|
|
want string
|
|
}{
|
|
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State.On -> 1 } }`, "missing Off"},
|
|
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State.On -> 1 State.Off -> "off" } }`, "has type String, expected Int"},
|
|
} {
|
|
prog, err := Parse(test.source)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = GenerateGo(prog)
|
|
if err == nil || !strings.Contains(err.Error(), test.want) {
|
|
t.Fatalf("expected %q, got %v", test.want, err)
|
|
}
|
|
}
|
|
}
|