github.com/go-swagger/go-swagger@v0.31.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  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  // only used within this group of tests but never used within actual code base.
    16  func newSchemaAnnotationParser(goName string) *schemaAnnotationParser {
    17  	return &schemaAnnotationParser{GoName: goName, rx: rxModelOverride}
    18  }
    19  
    20  type schemaAnnotationParser struct {
    21  	GoName string
    22  	Name   string
    23  	rx     *regexp.Regexp
    24  }
    25  
    26  func (sap *schemaAnnotationParser) Matches(line string) bool {
    27  	return sap.rx.MatchString(line)
    28  }
    29  
    30  func (sap *schemaAnnotationParser) Parse(lines []string) error {
    31  	if sap.Name != "" {
    32  		return nil
    33  	}
    34  
    35  	if len(lines) > 0 {
    36  		for _, line := range lines {
    37  			matches := sap.rx.FindStringSubmatch(line)
    38  			if len(matches) > 1 && len(matches[1]) > 0 {
    39  				sap.Name = matches[1]
    40  				return nil
    41  			}
    42  		}
    43  	}
    44  	return nil
    45  }
    46  
    47  func TestSectionedParser_TitleDescription(t *testing.T) {
    48  	text := `This has a title, separated by a whitespace line
    49  
    50  In this example the punctuation for the title should not matter for swagger.
    51  For go it will still make a difference though.
    52  `
    53  	text2 := `This has a title without whitespace.
    54  The punctuation here does indeed matter. But it won't for go.
    55  `
    56  
    57  	text3 := `This has a title, and markdown in the description
    58  
    59  See how markdown works now, we can have lists:
    60  
    61  + first item
    62  + second item
    63  + third item
    64  
    65  [Links works too](http://localhost)
    66  `
    67  
    68  	text4 := `This has whitespace sensitive markdown in the description
    69  
    70  |+ first item
    71  |    + nested item
    72  |    + also nested item
    73  
    74  Sample code block:
    75  
    76  |    fmt.Println("Hello World!")
    77  
    78  `
    79  
    80  	var err error
    81  
    82  	st := &sectionedParser{}
    83  	st.setTitle = func(_ []string) {}
    84  	err = st.Parse(ascg(text))
    85  	require.NoError(t, err)
    86  
    87  	assert.EqualValues(t, []string{"This has a title, separated by a whitespace line"}, st.Title())
    88  	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())
    89  
    90  	st = &sectionedParser{}
    91  	st.setTitle = func(_ []string) {}
    92  	err = st.Parse(ascg(text2))
    93  	require.NoError(t, err)
    94  
    95  	assert.EqualValues(t, []string{"This has a title without whitespace."}, st.Title())
    96  	assert.EqualValues(t, []string{"The punctuation here does indeed matter. But it won't for go."}, st.Description())
    97  
    98  	st = &sectionedParser{}
    99  	st.setTitle = func(_ []string) {}
   100  	err = st.Parse(ascg(text3))
   101  	require.NoError(t, err)
   102  
   103  	assert.EqualValues(t, []string{"This has a title, and markdown in the description"}, st.Title())
   104  	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())
   105  
   106  	st = &sectionedParser{}
   107  	st.setTitle = func(_ []string) {}
   108  	err = st.Parse(ascg(text4))
   109  	require.NoError(t, err)
   110  
   111  	assert.EqualValues(t, []string{"This has whitespace sensitive markdown in the description"}, st.Title())
   112  	assert.EqualValues(t, []string{"+ first item", "    + nested item", "    + also nested item", "", "Sample code block:", "", "    fmt.Println(\"Hello World!\")"}, st.Description())
   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 := &sectionedParser{}
   135  	st.setTitle = func(_ []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  	require.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 = &sectionedParser{}
   153  	st.setTitle = func(_ []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  	require.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 := &sectionedParser{}
   177  	st.setTitle = func(_ []string) {}
   178  	ap := newSchemaAnnotationParser("SomeResponse")
   179  	ap.rx = rxResponseOverride
   180  	st.annotation = ap
   181  
   182  	err = st.Parse(ascg(block))
   183  	require.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 := &sectionedParser{}
   203  	st.setTitle = func(_ []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  	require.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 := &sectionedParser{}
   238  	st.setTitle = func(_ []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  	require.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  	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  	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  }