github.com/AngusLu/go-swagger@v0.28.0/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 := &sectionedParser{}
    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 = &sectionedParser{}
    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 = &sectionedParser{}
    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 = &sectionedParser{}
   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  func dummyBuilder() schemaValidations {
   115  	return schemaValidations{new(spec.Schema)}
   116  }
   117  
   118  func TestSectionedParser_TagsDescription(t *testing.T) {
   119  	block := `This has a title without whitespace.
   120  The punctuation here does indeed matter. But it won't for go.
   121  minimum: 10
   122  maximum: 20
   123  `
   124  	block2 := `This has a title without whitespace.
   125  The punctuation here does indeed matter. But it won't for go.
   126  
   127  minimum: 10
   128  maximum: 20
   129  `
   130  
   131  	var err error
   132  
   133  	st := &sectionedParser{}
   134  	st.setTitle = func(lines []string) {}
   135  	st.taggers = []tagParser{
   136  		{"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}},
   137  		{"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}},
   138  		{"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}},
   139  	}
   140  
   141  	err = st.Parse(ascg(block))
   142  	assert.NoError(t, err)
   143  	assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title())
   144  	assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description())
   145  	assert.Len(t, st.matched, 2)
   146  	_, ok := st.matched["Maximum"]
   147  	assert.True(t, ok)
   148  	_, ok = st.matched["Minimum"]
   149  	assert.True(t, ok)
   150  
   151  	st = &sectionedParser{}
   152  	st.setTitle = func(lines []string) {}
   153  	st.taggers = []tagParser{
   154  		{"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}},
   155  		{"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}},
   156  		{"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}},
   157  	}
   158  
   159  	err = st.Parse(ascg(block2))
   160  	assert.NoError(t, err)
   161  	assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title())
   162  	assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description())
   163  	assert.Len(t, st.matched, 2)
   164  	_, ok = st.matched["Maximum"]
   165  	assert.True(t, ok)
   166  	_, ok = st.matched["Minimum"]
   167  	assert.True(t, ok)
   168  }
   169  
   170  func TestSectionedParser_Empty(t *testing.T) {
   171  	block := `swagger:response someResponse`
   172  
   173  	var err error
   174  
   175  	st := &sectionedParser{}
   176  	st.setTitle = func(lines []string) {}
   177  	ap := newSchemaAnnotationParser("SomeResponse")
   178  	ap.rx = rxResponseOverride
   179  	st.annotation = ap
   180  
   181  	err = st.Parse(ascg(block))
   182  	assert.NoError(t, err)
   183  	assert.Empty(t, st.Title())
   184  	assert.Empty(t, st.Description())
   185  	assert.Empty(t, st.taggers)
   186  	assert.Equal(t, "SomeResponse", ap.GoName)
   187  	assert.Equal(t, "someResponse", ap.Name)
   188  }
   189  
   190  func TestSectionedParser_SkipSectionAnnotation(t *testing.T) {
   191  	block := `swagger:model someModel
   192  
   193  This has a title without whitespace.
   194  The punctuation here does indeed matter. But it won't for go.
   195  
   196  minimum: 10
   197  maximum: 20
   198  `
   199  	var err error
   200  
   201  	st := &sectionedParser{}
   202  	st.setTitle = func(lines []string) {}
   203  	ap := newSchemaAnnotationParser("SomeModel")
   204  	st.annotation = ap
   205  	st.taggers = []tagParser{
   206  		{"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}},
   207  		{"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}},
   208  		{"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}},
   209  	}
   210  
   211  	err = st.Parse(ascg(block))
   212  	assert.NoError(t, err)
   213  	assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title())
   214  	assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description())
   215  	assert.Len(t, st.matched, 2)
   216  	_, ok := st.matched["Maximum"]
   217  	assert.True(t, ok)
   218  	_, ok = st.matched["Minimum"]
   219  	assert.True(t, ok)
   220  	assert.Equal(t, "SomeModel", ap.GoName)
   221  	assert.Equal(t, "someModel", ap.Name)
   222  }
   223  
   224  func TestSectionedParser_TerminateOnNewAnnotation(t *testing.T) {
   225  	block := `swagger:model someModel
   226  
   227  This has a title without whitespace.
   228  The punctuation here does indeed matter. But it won't for go.
   229  
   230  minimum: 10
   231  swagger:meta
   232  maximum: 20
   233  `
   234  	var err error
   235  
   236  	st := &sectionedParser{}
   237  	st.setTitle = func(lines []string) {}
   238  	ap := newSchemaAnnotationParser("SomeModel")
   239  	st.annotation = ap
   240  	st.taggers = []tagParser{
   241  		{"Maximum", false, false, nil, &setMaximum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMaximumFmt, ""))}},
   242  		{"Minimum", false, false, nil, &setMinimum{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMinimumFmt, ""))}},
   243  		{"MultipleOf", false, false, nil, &setMultipleOf{dummyBuilder(), regexp.MustCompile(fmt.Sprintf(rxMultipleOfFmt, ""))}},
   244  	}
   245  
   246  	err = st.Parse(ascg(block))
   247  	assert.NoError(t, err)
   248  	assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title())
   249  	assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description())
   250  	assert.Len(t, st.matched, 1)
   251  	_, ok := st.matched["Maximum"]
   252  	assert.False(t, ok)
   253  	_, ok = st.matched["Minimum"]
   254  	assert.True(t, ok)
   255  	assert.Equal(t, "SomeModel", ap.GoName)
   256  	assert.Equal(t, "someModel", ap.Name)
   257  }
   258  
   259  func ascg(txt string) *ast.CommentGroup {
   260  	var cg ast.CommentGroup
   261  	for _, line := range strings.Split(txt, "\n") {
   262  		var cmt ast.Comment
   263  		cmt.Text = "// " + line
   264  		cg.List = append(cg.List, &cmt)
   265  	}
   266  	return &cg
   267  }
   268  
   269  func TestShouldAcceptTag(t *testing.T) {
   270  	var tagTests = []struct {
   271  		tags        []string
   272  		includeTags map[string]bool
   273  		excludeTags map[string]bool
   274  		expected    bool
   275  	}{
   276  		{nil, nil, nil, true},
   277  		{[]string{"app"}, map[string]bool{"app": true}, nil, true},
   278  		{[]string{"app"}, nil, map[string]bool{"app": true}, false},
   279  	}
   280  	for _, tt := range tagTests {
   281  		actual := shouldAcceptTag(tt.tags, tt.includeTags, tt.excludeTags)
   282  		assert.Equal(t, tt.expected, actual)
   283  	}
   284  }
   285  
   286  func TestShouldAcceptPkg(t *testing.T) {
   287  	var pkgTests = []struct {
   288  		path        string
   289  		includePkgs []string
   290  		excludePkgs []string
   291  		expected    bool
   292  	}{
   293  		{"", nil, nil, true},
   294  		{"", nil, []string{"app"}, true},
   295  		{"", []string{"app"}, nil, false},
   296  		{"app", []string{"app"}, nil, true},
   297  		{"app", nil, []string{"app"}, false},
   298  		{"vendor/app", []string{"app"}, nil, true},
   299  		{"vendor/app", nil, []string{"app"}, false},
   300  	}
   301  	for _, tt := range pkgTests {
   302  		actual := shouldAcceptPkg(tt.path, tt.includePkgs, tt.excludePkgs)
   303  		assert.Equal(t, tt.expected, actual)
   304  	}
   305  }