package lang import ( "strings" "testing" ) func TestSafeAccessAndNonNullAssertion(t *testing.T) { prog, err := Parse(`package demo data class User(var email: String) fun safe(user: *User?): String? { return user?.email } fun required(user: *User?): String { return user!!.email }`) if err != nil { t.Fatal(err) } out, err := GenerateGo(prog) if err != nil { t.Fatal(err) } for _, want := range []string{"if value == nil {", "return &result", "non-null assertion failed"} { if !strings.Contains(string(out), want) { t.Fatalf("missing %q:\n%s", want, out) } } } func TestRejectNullableDereference(t *testing.T) { prog, err := Parse(`package demo fun unsafe(user: *User?): String { return user.email }`) if err != nil { t.Fatal(err) } _, err = GenerateGo(prog) if err == nil || !strings.Contains(err.Error(), "requires ?. or !!") { t.Fatalf("unexpected error: %v", err) } } func TestRejectNullForNonNullableTypes(t *testing.T) { for _, source := range []string{ `package demo data class User(var email: String) fun main() { val user: *User = null }`, `package demo data class User(var email: String) fun use(user: *User) {} fun main() { use(null) }`, `package demo fun name(): String { return null }`, `package demo fun main() { val value = null }`, } { prog, err := Parse(source) if err != nil { t.Fatal(err) } if _, err = GenerateGo(prog); err == nil { t.Fatalf("expected nullability error for %s", source) } } } func TestNullableSmartCasts(t *testing.T) { prog, err := Parse(`package demo data class User(var email: String) fun guarded(user: *User?): String { if (user == null) { return "missing" }; return user.email } fun branched(user: *User?): String { if (user != null) { return user.email } else { return "missing" } }`) if err != nil { t.Fatal(err) } if _, err = GenerateGo(prog); err != nil { t.Fatal(err) } }