TestRecursiveValidationWithCycleGuard tests that recursive types are properly handled without infinite loops. The recursion guard should prevent cycles while still allowing validation of the same type in different contexts.
(t *testing.T)
| 96 | // properly handled without infinite loops. The recursion guard should prevent |
| 97 | // cycles while still allowing validation of the same type in different contexts. |
| 98 | func TestRecursiveValidationWithCycleGuard(t *testing.T) { |
| 99 | root := RunDSL(t, testdata.RecursiveValidationDSL) |
| 100 | scope := NewNameScope() |
| 101 | |
| 102 | cases := []struct { |
| 103 | Name string |
| 104 | TypeName string |
| 105 | Pointer bool |
| 106 | }{ |
| 107 | {"recursive-type-pointer", "RecursiveType", true}, |
| 108 | {"recursive-type-required", "RecursiveType", false}, |
| 109 | {"container-with-recursive-array", "ContainerWithRecursiveArray", true}, |
| 110 | {"container-with-recursive-map", "ContainerWithRecursiveMap", true}, |
| 111 | {"nested-recursive-pointer", "NestedRecursive", true}, |
| 112 | } |
| 113 | |
| 114 | for _, c := range cases { |
| 115 | t.Run(c.Name, func(t *testing.T) { |
| 116 | ctx := NewAttributeContext(c.Pointer, false, false, "", scope) |
| 117 | ut := root.UserType(c.TypeName) |
| 118 | code := ValidationCode(&expr.AttributeExpr{Type: ut}, nil, ctx, !c.Pointer, false, false, "target") |
| 119 | // Verify code is generated (not empty) and doesn't cause infinite recursion |
| 120 | if code == "" { |
| 121 | t.Error("Expected validation code to be generated") |
| 122 | } |
| 123 | // Verify the code can be formatted (indicates valid Go code) |
| 124 | code = FormatTestCode(t, "package foo\nfunc Validate() (err error){\n"+code+"}") |
| 125 | if code == "" { |
| 126 | t.Error("Expected formatted code to be generated") |
| 127 | } |
| 128 | }) |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | // TestMultipleAliasTypesInSameStruct tests that multiple fields with the same |
| 133 | // alias type can be validated independently. Previously, the recursion guard |
nothing calls this directly
no test coverage detected