1package bpdoc 2 3import ( 4 "fmt" 5 "reflect" 6 "testing" 7) 8 9type propInfo struct { 10 name string 11 typ string 12} 13 14type parentProps struct { 15 A string 16 17 Child *childProps 18 19 Mutated *mutatedProps `blueprint:"mutated"` 20} 21 22type childProps struct { 23 B int 24 25 Child *grandchildProps 26} 27 28type grandchildProps struct { 29 C bool 30} 31 32type mutatedProps struct { 33 D int 34} 35 36func TestNestedPropertyStructs(t *testing.T) { 37 parent := parentProps{Child: &childProps{Child: &grandchildProps{}}, Mutated: &mutatedProps{}} 38 39 allStructs := nestedPropertyStructs(reflect.ValueOf(parent)) 40 41 // mutated shouldn't be found because it's a mutated property. 42 expected := []string{"child", "child.child"} 43 if len(allStructs) != len(expected) { 44 t.Fatalf("expected %d structs, got %d, all entries: %v", 45 len(expected), len(allStructs), allStructs) 46 } 47 got := []string{} 48 for _, s := range allStructs { 49 got = append(got, s.nestPoint) 50 } 51 52 if !reflect.DeepEqual(got, expected) { 53 t.Errorf("Expected nested properties:\n\t %q,\n but got\n\t %q", expected, got) 54 } 55} 56 57func TestAllPackages(t *testing.T) { 58 packages, err := AllPackages(pkgFiles, moduleTypeNameFactories, moduleTypeNamePropertyStructs) 59 if err != nil { 60 t.Fatalf("expected nil error for AllPackages(%v, %v, %v), got %s", pkgFiles, moduleTypeNameFactories, moduleTypeNamePropertyStructs, err) 61 } 62 63 if numPackages := len(packages); numPackages != 1 { 64 t.Errorf("Expected %d package, got %d packages %v instead", len(pkgFiles), numPackages, packages) 65 } 66 67 pkg := packages[0] 68 69 expectedProps := map[string][]propInfo{ 70 "bar": []propInfo{ 71 propInfo{ 72 name: "a", 73 typ: "string", 74 }, 75 propInfo{ 76 name: "nested", 77 typ: "", 78 }, 79 propInfo{ 80 name: "nested.c", 81 typ: "string", 82 }, 83 propInfo{ 84 name: "nested_struct", 85 typ: "structToNest", 86 }, 87 propInfo{ 88 name: "nested_struct.e", 89 typ: "string", 90 }, 91 propInfo{ 92 name: "struct_has_embed", 93 typ: "StructWithEmbedded", 94 }, 95 propInfo{ 96 name: "struct_has_embed.nested_in_embedded", 97 typ: "structToNest", 98 }, 99 propInfo{ 100 name: "struct_has_embed.nested_in_embedded.e", 101 typ: "string", 102 }, 103 propInfo{ 104 name: "struct_has_embed.f", 105 typ: "string", 106 }, 107 propInfo{ 108 name: "list_of_ints", 109 typ: "list of int", 110 }, 111 propInfo{ 112 name: "list_of_nested", 113 typ: "list of structToNest", 114 }, 115 propInfo{ 116 name: "nested_in_other_embedded", 117 typ: "otherStructToNest", 118 }, 119 propInfo{ 120 name: "nested_in_other_embedded.g", 121 typ: "string", 122 }, 123 propInfo{ 124 name: "h", 125 typ: "string", 126 }, 127 }, 128 "foo": []propInfo{ 129 propInfo{ 130 name: "a", 131 typ: "string", 132 }, 133 }, 134 } 135 136 for _, m := range pkg.ModuleTypes { 137 foundProps := []propInfo{} 138 139 for _, p := range m.PropertyStructs { 140 nestedProps, errs := findAllProperties("", p.Properties) 141 foundProps = append(foundProps, nestedProps...) 142 for _, err := range errs { 143 t.Errorf("%s", err) 144 } 145 } 146 if wanted, ok := expectedProps[m.Name]; ok { 147 if !reflect.DeepEqual(foundProps, wanted) { 148 t.Errorf("For %s, expected\n\t %q,\nbut got\n\t %q", m.Name, wanted, foundProps) 149 } 150 } 151 } 152} 153 154func findAllProperties(prefix string, properties []Property) ([]propInfo, []error) { 155 foundProps := []propInfo{} 156 errs := []error{} 157 for _, p := range properties { 158 prop := propInfo{ 159 name: prefix + p.Name, 160 typ: p.Type, 161 } 162 foundProps = append(foundProps, prop) 163 if hasTag(p.Tag, "blueprint", "mutated") { 164 err := fmt.Errorf("Property %s has `blueprint:\"mutated\" tag but should have been excluded.", p.Name) 165 errs = append(errs, err) 166 } 167 168 nestedProps, nestedErrs := findAllProperties(prefix+p.Name+".", p.Properties) 169 foundProps = append(foundProps, nestedProps...) 170 errs = append(errs, nestedErrs...) 171 } 172 return foundProps, errs 173} 174