github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/codescan/parser_test.go (about) 1 package codescan 2 3 import ( 4 "fmt" 5 "go/ast" 6 "regexp" 7 "strings" 8 "testing" 9 10 "github.com/go-openapi/spec" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 // only used within this group of tests but never used within actual code base. 15 func newSchemaAnnotationParser(goName string) *schemaAnnotationParser { 16 return &schemaAnnotationParser{GoName: goName, rx: rxModelOverride} 17 } 18 19 type schemaAnnotationParser struct { 20 GoName string 21 Name string 22 rx *regexp.Regexp 23 } 24 25 func (sap *schemaAnnotationParser) Matches(line string) bool { 26 return sap.rx.MatchString(line) 27 } 28 29 func (sap *schemaAnnotationParser) Parse(lines []string) error { 30 if sap.Name != "" { 31 return nil 32 } 33 34 if len(lines) > 0 { 35 for _, line := range lines { 36 matches := sap.rx.FindStringSubmatch(line) 37 if len(matches) > 1 && len(matches[1]) > 0 { 38 sap.Name = matches[1] 39 return nil 40 } 41 } 42 } 43 return nil 44 } 45 46 func TestSectionedParser_TitleDescription(t *testing.T) { 47 text := `This has a title, separated by a whitespace line 48 49 In this example the punctuation for the title should not matter for swagger. 50 For go it will still make a difference though. 51 ` 52 text2 := `This has a title without whitespace. 53 The punctuation here does indeed matter. But it won't for go. 54 ` 55 56 text3 := `This has a title, and markdown in the description 57 58 See how markdown works now, we can have lists: 59 60 + first item 61 + second item 62 + third item 63 64 [Links works too](http://localhost) 65 ` 66 67 text4 := `This has whitespace sensitive markdown in the description 68 69 |+ first item 70 | + nested item 71 | + also nested item 72 73 Sample code block: 74 75 | fmt.Println("Hello World!") 76 77 ` 78 79 var err error 80 81 st := §ionedParser{} 82 st.setTitle = func(lines []string) {} 83 err = st.Parse(ascg(text)) 84 assert.NoError(t, err) 85 86 assert.EqualValues(t, []string{"This has a title, separated by a whitespace line"}, st.Title()) 87 assert.EqualValues(t, []string{"In this example the punctuation for the title should not matter for swagger.", "For go it will still make a difference though."}, st.Description()) 88 89 st = §ionedParser{} 90 st.setTitle = func(lines []string) {} 91 err = st.Parse(ascg(text2)) 92 assert.NoError(t, err) 93 94 assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title()) 95 assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description()) 96 97 st = §ionedParser{} 98 st.setTitle = func(lines []string) {} 99 err = st.Parse(ascg(text3)) 100 assert.NoError(t, err) 101 102 assert.EqualValues(t, []string{"This has a title, and markdown in the description"}, st.Title()) 103 assert.EqualValues(t, []string{"See how markdown works now, we can have lists:", "", "+ first item", "+ second item", "+ third item", "", "[Links works too](http://localhost)"}, st.Description()) 104 105 st = §ionedParser{} 106 st.setTitle = func(lines []string) {} 107 err = st.Parse(ascg(text4)) 108 assert.NoError(t, err) 109 110 assert.EqualValues(t, []string{"This has whitespace sensitive markdown in the description"}, st.Title()) 111 assert.EqualValues(t, []string{"+ first item", " + nested item", " + also nested item", "", "Sample code block:", "", " fmt.Println(\"Hello World!\")"}, st.Description()) 112 113 } 114 115 func dummyBuilder() schemaValidations { 116 return schemaValidations{new(spec.Schema)} 117 } 118 119 func TestSectionedParser_TagsDescription(t *testing.T) { 120 block := `This has a title without whitespace. 121 The punctuation here does indeed matter. But it won't for go. 122 minimum: 10 123 maximum: 20 124 ` 125 block2 := `This has a title without whitespace. 126 The punctuation here does indeed matter. But it won't for go. 127 128 minimum: 10 129 maximum: 20 130 ` 131 132 var err error 133 134 st := §ionedParser{} 135 st.setTitle = func(lines []string) {} 136 st.taggers = []tagParser{ 137 {"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}}, 138 {"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}}, 139 {"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}}, 140 } 141 142 err = st.Parse(ascg(block)) 143 assert.NoError(t, err) 144 assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title()) 145 assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description()) 146 assert.Len(t, st.matched, 2) 147 _, ok := st.matched["Maximum"] 148 assert.True(t, ok) 149 _, ok = st.matched["Minimum"] 150 assert.True(t, ok) 151 152 st = §ionedParser{} 153 st.setTitle = func(lines []string) {} 154 st.taggers = []tagParser{ 155 {"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}}, 156 {"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}}, 157 {"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}}, 158 } 159 160 err = st.Parse(ascg(block2)) 161 assert.NoError(t, err) 162 assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title()) 163 assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description()) 164 assert.Len(t, st.matched, 2) 165 _, ok = st.matched["Maximum"] 166 assert.True(t, ok) 167 _, ok = st.matched["Minimum"] 168 assert.True(t, ok) 169 } 170 171 func TestSectionedParser_Empty(t *testing.T) { 172 block := `swagger:response someResponse` 173 174 var err error 175 176 st := §ionedParser{} 177 st.setTitle = func(lines []string) {} 178 ap := newSchemaAnnotationParser("SomeResponse") 179 ap.rx = rxResponseOverride 180 st.annotation = ap 181 182 err = st.Parse(ascg(block)) 183 assert.NoError(t, err) 184 assert.Empty(t, st.Title()) 185 assert.Empty(t, st.Description()) 186 assert.Empty(t, st.taggers) 187 assert.Equal(t, "SomeResponse", ap.GoName) 188 assert.Equal(t, "someResponse", ap.Name) 189 } 190 191 func TestSectionedParser_SkipSectionAnnotation(t *testing.T) { 192 block := `swagger:model someModel 193 194 This has a title without whitespace. 195 The punctuation here does indeed matter. But it won't for go. 196 197 minimum: 10 198 maximum: 20 199 ` 200 var err error 201 202 st := §ionedParser{} 203 st.setTitle = func(lines []string) {} 204 ap := newSchemaAnnotationParser("SomeModel") 205 st.annotation = ap 206 st.taggers = []tagParser{ 207 {"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}}, 208 {"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}}, 209 {"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}}, 210 } 211 212 err = st.Parse(ascg(block)) 213 assert.NoError(t, err) 214 assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title()) 215 assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description()) 216 assert.Len(t, st.matched, 2) 217 _, ok := st.matched["Maximum"] 218 assert.True(t, ok) 219 _, ok = st.matched["Minimum"] 220 assert.True(t, ok) 221 assert.Equal(t, "SomeModel", ap.GoName) 222 assert.Equal(t, "someModel", ap.Name) 223 } 224 225 func TestSectionedParser_TerminateOnNewAnnotation(t *testing.T) { 226 block := `swagger:model someModel 227 228 This has a title without whitespace. 229 The punctuation here does indeed matter. But it won't for go. 230 231 minimum: 10 232 swagger:meta 233 maximum: 20 234 ` 235 var err error 236 237 st := §ionedParser{} 238 st.setTitle = func(lines []string) {} 239 ap := newSchemaAnnotationParser("SomeModel") 240 st.annotation = ap 241 st.taggers = []tagParser{ 242 {"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}}, 243 {"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}}, 244 {"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}}, 245 } 246 247 err = st.Parse(ascg(block)) 248 assert.NoError(t, err) 249 assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title()) 250 assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description()) 251 assert.Len(t, st.matched, 1) 252 _, ok := st.matched["Maximum"] 253 assert.False(t, ok) 254 _, ok = st.matched["Minimum"] 255 assert.True(t, ok) 256 assert.Equal(t, "SomeModel", ap.GoName) 257 assert.Equal(t, "someModel", ap.Name) 258 } 259 260 func ascg(txt string) *ast.CommentGroup { 261 var cg ast.CommentGroup 262 for _, line := range strings.Split(txt, "\n") { 263 var cmt ast.Comment 264 cmt.Text = "// " + line 265 cg.List = append(cg.List, &cmt) 266 } 267 return &cg 268 } 269 270 func TestShouldAcceptTag(t *testing.T) { 271 var tagTests = []struct { 272 tags []string 273 includeTags map[string]bool 274 excludeTags map[string]bool 275 expected bool 276 }{ 277 {nil, nil, nil, true}, 278 {[]string{"app"}, map[string]bool{"app": true}, nil, true}, 279 {[]string{"app"}, nil, map[string]bool{"app": true}, false}, 280 } 281 for _, tt := range tagTests { 282 actual := shouldAcceptTag(tt.tags, tt.includeTags, tt.excludeTags) 283 assert.Equal(t, tt.expected, actual) 284 } 285 } 286 287 func TestShouldAcceptPkg(t *testing.T) { 288 var pkgTests = []struct { 289 path string 290 includePkgs []string 291 excludePkgs []string 292 expected bool 293 }{ 294 {"", nil, nil, true}, 295 {"", nil, []string{"app"}, true}, 296 {"", []string{"app"}, nil, false}, 297 {"app", []string{"app"}, nil, true}, 298 {"app", nil, []string{"app"}, false}, 299 {"vendor/app", []string{"app"}, nil, true}, 300 {"vendor/app", nil, []string{"app"}, false}, 301 } 302 for _, tt := range pkgTests { 303 actual := shouldAcceptPkg(tt.path, tt.includePkgs, tt.excludePkgs) 304 assert.Equal(t, tt.expected, actual) 305 } 306 }