...

Source file src/github.com/go-openapi/spec/helpers_test.go

Documentation: github.com/go-openapi/spec

     1  package spec
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/go-openapi/swag"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  var rex = regexp.MustCompile(`"\$ref":\s*"(.*?)"`)
    16  
    17  func jsonDoc(path string) (json.RawMessage, error) {
    18  	data, err := swag.LoadFromFileOrHTTP(path)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	return json.RawMessage(data), nil
    23  }
    24  
    25  func docAndOpts(t testing.TB, fixturePath string) ([]byte, *ExpandOptions) {
    26  	doc, err := jsonDoc(fixturePath)
    27  	require.NoError(t, err)
    28  
    29  	return doc, &ExpandOptions{
    30  		RelativeBase: fixturePath,
    31  	}
    32  }
    33  
    34  func expandThisSchemaOrDieTrying(t testing.TB, fixturePath string) (string, *Schema) {
    35  	doc, opts := docAndOpts(t, fixturePath)
    36  
    37  	sch := new(Schema)
    38  	require.NoError(t, json.Unmarshal(doc, sch))
    39  
    40  	require.NotPanics(t, func() {
    41  		require.NoError(t, ExpandSchemaWithBasePath(sch, nil, opts))
    42  	}, "calling expand schema circular refs, should not panic!")
    43  
    44  	bbb, err := json.MarshalIndent(sch, "", " ")
    45  	require.NoError(t, err)
    46  
    47  	return string(bbb), sch
    48  }
    49  
    50  func expandThisOrDieTrying(t testing.TB, fixturePath string) (string, *Swagger) {
    51  	doc, opts := docAndOpts(t, fixturePath)
    52  
    53  	spec := new(Swagger)
    54  	require.NoError(t, json.Unmarshal(doc, spec))
    55  
    56  	require.NotPanics(t, func() {
    57  		require.NoError(t, ExpandSpec(spec, opts))
    58  	}, "calling expand spec with circular refs, should not panic!")
    59  
    60  	bbb, err := json.MarshalIndent(spec, "", " ")
    61  	require.NoError(t, err)
    62  
    63  	return string(bbb), spec
    64  }
    65  
    66  // assertRefInJSONRegexp ensures all $ref in a jazon document have a given prefix.
    67  //
    68  // NOTE: matched $ref might be empty.
    69  func assertRefInJSON(t testing.TB, jazon, prefix string) {
    70  	// assert a match in a references
    71  	m := rex.FindAllStringSubmatch(jazon, -1)
    72  	require.NotNil(t, m)
    73  
    74  	for _, matched := range m {
    75  		subMatch := matched[1]
    76  		assert.True(t, strings.HasPrefix(subMatch, prefix),
    77  			"expected $ref to match %q, got: %s", prefix, matched[0])
    78  	}
    79  }
    80  
    81  // assertRefInJSONRegexp ensures all $ref in a jazon document match a given regexp
    82  //
    83  // NOTE: matched $ref might be empty.
    84  func assertRefInJSONRegexp(t testing.TB, jazon, match string) {
    85  	// assert a match in a references
    86  	m := rex.FindAllStringSubmatch(jazon, -1)
    87  	require.NotNil(t, m)
    88  
    89  	refMatch, err := regexp.Compile(match)
    90  	require.NoError(t, err)
    91  
    92  	for _, matched := range m {
    93  		subMatch := matched[1]
    94  		assert.True(t, refMatch.MatchString(subMatch),
    95  			"expected $ref to match %q, got: %s", match, matched[0])
    96  	}
    97  }
    98  
    99  // assertNoRef ensures that no $ref is remaining in json doc
   100  func assertNoRef(t testing.TB, jazon string) {
   101  	m := rex.FindAllStringSubmatch(jazon, -1)
   102  	require.Nil(t, m)
   103  }
   104  
   105  // assertRefExpand ensures that all $ref in some json doc expand properly against a root document.
   106  //
   107  // "exclude" is a regexp pattern to ignore certain $ref (e.g. some specs may embed $ref that are not processed, such as extensions).
   108  func assertRefExpand(t *testing.T, jazon, _ string, root interface{}, opts ...*ExpandOptions) {
   109  	assertRefWithFunc(t, jazon, "", func(t *testing.T, match string) {
   110  		ref := RefSchema(match)
   111  		if len(opts) > 0 {
   112  			options := *opts[0]
   113  			require.NoError(t, ExpandSchemaWithBasePath(ref, nil, &options))
   114  		} else {
   115  			require.NoError(t, ExpandSchema(ref, root, nil))
   116  		}
   117  	})
   118  }
   119  
   120  // assertRefResolve ensures that all $ref in some json doc resolve properly against a root document.
   121  //
   122  // "exclude" is a regexp pattern to ignore certain $ref (e.g. some specs may embed $ref that are not processed, such as extensions).
   123  func assertRefResolve(t *testing.T, jazon, exclude string, root interface{}, opts ...*ExpandOptions) {
   124  	assertRefWithFunc(t, jazon, exclude, func(t *testing.T, match string) {
   125  		ref := MustCreateRef(match)
   126  		var (
   127  			sch *Schema
   128  			err error
   129  		)
   130  		if len(opts) > 0 {
   131  			options := *opts[0]
   132  			sch, err = ResolveRefWithBase(root, &ref, &options)
   133  		} else {
   134  			sch, err = ResolveRef(root, &ref)
   135  		}
   136  
   137  		require.NoErrorf(t, err, `%v: for "$ref": %q`, err, match)
   138  		require.NotNil(t, sch)
   139  	})
   140  }
   141  
   142  // assertRefResolve ensures that all $ref in some json doc verify some asserting func.
   143  //
   144  // "exclude" is a regexp pattern to ignore certain $ref (e.g. some specs may embed $ref that are not processed, such as extensions).
   145  func assertRefWithFunc(t *testing.T, jazon, exclude string, asserter func(t *testing.T, match string)) {
   146  	filterRex := regexp.MustCompile(exclude)
   147  	m := rex.FindAllStringSubmatch(jazon, -1)
   148  	require.NotNil(t, m)
   149  	allRefs := make(map[string]struct{}, len(m))
   150  	for _, matched := range m {
   151  		subMatch := matched[1]
   152  		if exclude != "" && filterRex.MatchString(subMatch) {
   153  			continue
   154  		}
   155  		_, ok := allRefs[subMatch]
   156  		if ok {
   157  			continue
   158  		}
   159  		allRefs[subMatch] = struct{}{}
   160  
   161  		t.Run(fmt.Sprintf("%s-%s", t.Name(), subMatch), func(t *testing.T) {
   162  			t.Parallel()
   163  			asserter(t, subMatch)
   164  		})
   165  	}
   166  }
   167  
   168  func asJSON(t testing.TB, sp interface{}) string {
   169  	bbb, err := json.MarshalIndent(sp, "", " ")
   170  	require.NoError(t, err)
   171  
   172  	return string(bbb)
   173  }
   174  

View as plain text